| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package XML::Writer::Simple; | 
| 2 |  |  |  |  |  |  | $XML::Writer::Simple::VERSION = '0.12'; | 
| 3 | 7 |  |  | 7 |  | 146617 | use warnings; | 
|  | 7 |  |  |  |  | 15 |  | 
|  | 7 |  |  |  |  | 268 |  | 
| 4 | 7 |  |  | 7 |  | 39 | use strict; | 
|  | 7 |  |  |  |  | 9 |  | 
|  | 7 |  |  |  |  | 235 |  | 
| 5 | 7 |  |  | 7 |  | 35 | use Exporter (); | 
|  | 7 |  |  |  |  | 22 |  | 
|  | 7 |  |  |  |  | 151 |  | 
| 6 | 7 |  |  | 7 |  | 51 | use vars qw/@ISA @EXPORT/; | 
|  | 7 |  |  |  |  | 14 |  | 
|  | 7 |  |  |  |  | 451 |  | 
| 7 | 7 |  |  | 7 |  | 6771 | use XML::DT; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | use XML::DTDParser qw/ParseDTDFile/; | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | =encoding utf-8 | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | =head1 NAME | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | XML::Writer::Simple - Create XML files easily! | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | =cut | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | @ISA = qw/Exporter/; | 
| 19 |  |  |  |  |  |  | @EXPORT = (qw/powertag xml_header quote_entities/); | 
| 20 |  |  |  |  |  |  | our %PTAGS = (); | 
| 21 |  |  |  |  |  |  | our $MODULENAME = "XML::Writer::Simple"; | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | our $IS_HTML = 0; | 
| 24 |  |  |  |  |  |  | our %TAG_SET = ( | 
| 25 |  |  |  |  |  |  | html => { | 
| 26 |  |  |  |  |  |  | tags => [qw.a abbr acronym address area | 
| 27 |  |  |  |  |  |  | b base bdo big blockquote body br button | 
| 28 |  |  |  |  |  |  | caption cite code col colgroup | 
| 29 |  |  |  |  |  |  | dd del dfn div dl dt | 
| 30 |  |  |  |  |  |  | em | 
| 31 |  |  |  |  |  |  | fieldset form frame frameset | 
| 32 |  |  |  |  |  |  | h1 h2 h3 h4 h5 h6 head hr html | 
| 33 |  |  |  |  |  |  | i iframe img input ins | 
| 34 |  |  |  |  |  |  | kbd | 
| 35 |  |  |  |  |  |  | label legend li link | 
| 36 |  |  |  |  |  |  | map meta | 
| 37 |  |  |  |  |  |  | noframes noscript | 
| 38 |  |  |  |  |  |  | object ol optgroup option | 
| 39 |  |  |  |  |  |  | p param pre | 
| 40 |  |  |  |  |  |  | q | 
| 41 |  |  |  |  |  |  | samp script select small span strong style sub sup | 
| 42 |  |  |  |  |  |  | table tbody td textarea tfoot th thead title Tr tt | 
| 43 |  |  |  |  |  |  | u ul var.] | 
| 44 |  |  |  |  |  |  | }, | 
| 45 |  |  |  |  |  |  | ); | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | use XML::Writer::Simple dtd => "file.dtd"; | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | print xml_header(encoding => 'iso-8859-1'); | 
| 52 |  |  |  |  |  |  | print para("foo",b("bar"),"zbr"); | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | # if you want CGI but you do not want CGI :) | 
| 56 |  |  |  |  |  |  | use XML::Writer::Simple ':html'; | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | =head1 USAGE | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | This module takes some ideas from CGI to make easier the life for | 
| 61 |  |  |  |  |  |  | those who need to generated XML code. You can use the module in three | 
| 62 |  |  |  |  |  |  | flavours (or combine them): | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | =over 4 | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | =item tags | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | When importing the module you can specify the tags you will be using: | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | use XML::Writer::Simple tags => [qw/p b i tt/]; | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | print p("Hey, ",b("you"),"! ", i("Yes ", b("you"))); | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | that will generate | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | Hey you! Yes you | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | =item dtd | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | You can supply a DTD, that will be analyzed, and the tags used: | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | use XML::Writer::Simple dtd => "tmx.dtd"; | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | print tu(seg("foo"),seg("bar")); | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  | =item xml | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | You can supply an XML (or a reference to a list of XML files). They | 
| 89 |  |  |  |  |  |  | will be parsed, and the tags used: | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | use XML::Writer::Simple xml => "foo.xml"; | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | print foo("bar"); | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | =item partial | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | You can supply an 'partial' key, to generate prototypes for partial tags | 
| 98 |  |  |  |  |  |  | construction. For instance: | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | use XML::Writer::Simple tags => qw/foo bar/, partial => 1; | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | print start_foo; | 
| 103 |  |  |  |  |  |  | print ... | 
| 104 |  |  |  |  |  |  | print end_foo; | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | =back | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | You can also use tagsets, where sets of tags from a well known format | 
| 109 |  |  |  |  |  |  | are imported. For example, to use HTML: | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | use XML::Writer::Simple ':html'; | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | =head1 EXPORT | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | This module export one function for each element at the dtd or xml | 
| 116 |  |  |  |  |  |  | file you are using. See below for details. | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | =head1 FUNCTIONS | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | =head2 import | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | Used when you 'use' the module, should not be used directly. | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | =head2 xml_header | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | This function returns the xml header string, without encoding | 
| 127 |  |  |  |  |  |  | definition, with a trailing new line. Default XML encoding should | 
| 128 |  |  |  |  |  |  | be UTF-8, by the way. | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | You can force an encoding passing it as argument: | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | print xml_header(encoding=>'iso-8859-1'); | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | =head2 powertag | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | Used to specify a powertag. For instance: | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | powertag("ul","li"); | 
| 139 |  |  |  |  |  |  |  | 
| 140 |  |  |  |  |  |  | ul_li([qw/foo bar zbr ugh/]); | 
| 141 |  |  |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | will generate | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | foo | 
| 146 |  |  |  |  |  |  | bar | 
| 147 |  |  |  |  |  |  | zbr | 
| 148 |  |  |  |  |  |  | ugh | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | You can also supply this information when loading the module, with | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | use XML::Writer::Simple powertags=>["ul_li","ol_li"]; | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | Powertags support three level tags as well: | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | use XML::Writer::Simple powertags=>["table_tr_td"]; | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | print table_tr_td(['a','b','c'],['d','e','f']); | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | =head2 quote_entities | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | To use the special characters C<< < >>, C<< > >> and C<< & >> on your PCDATA content you need | 
| 164 |  |  |  |  |  |  | to protect them. You can either do that yourself or call this function. | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | print f(quote_entities("a < b")); | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | =cut | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | sub xml_header { | 
| 171 |  |  |  |  |  |  | my %ops = @_; | 
| 172 |  |  |  |  |  |  | my $encoding = ""; | 
| 173 |  |  |  |  |  |  | $encoding =" encoding=\"$ops{encoding}\"" if exists $ops{encoding}; | 
| 174 |  |  |  |  |  |  | return "\n"; | 
| 175 |  |  |  |  |  |  | } | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | sub powertag { | 
| 178 |  |  |  |  |  |  | my $nfunc = join("_", @_); | 
| 179 |  |  |  |  |  |  | $PTAGS{$nfunc}=[@_]; | 
| 180 |  |  |  |  |  |  | push @EXPORT, $nfunc; | 
| 181 |  |  |  |  |  |  | XML::Writer::Simple->export_to_level(1, $MODULENAME, $nfunc); | 
| 182 |  |  |  |  |  |  | } | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | sub _xml_from { | 
| 185 |  |  |  |  |  |  | my ($tag, $attrs, @body) = @_; | 
| 186 |  |  |  |  |  |  | return (ref($body[0]) eq "ARRAY")? | 
| 187 |  |  |  |  |  |  | join("", map{ _toxml($tag, $attrs, $_) } @{$body[0]}) | 
| 188 |  |  |  |  |  |  | :_toxml($tag, $attrs, join("", @body)); | 
| 189 |  |  |  |  |  |  | } | 
| 190 |  |  |  |  |  |  |  | 
| 191 |  |  |  |  |  |  | sub _clean_attrs { | 
| 192 |  |  |  |  |  |  | my $attrs = shift; | 
| 193 |  |  |  |  |  |  | for (keys %$attrs) { | 
| 194 |  |  |  |  |  |  | if (m!^-!) { | 
| 195 |  |  |  |  |  |  | $attrs->{$'}=$attrs->{$_}; | 
| 196 |  |  |  |  |  |  | delete($attrs->{$_}); | 
| 197 |  |  |  |  |  |  | } | 
| 198 |  |  |  |  |  |  | } | 
| 199 |  |  |  |  |  |  | return $attrs; | 
| 200 |  |  |  |  |  |  | } | 
| 201 |  |  |  |  |  |  |  | 
| 202 |  |  |  |  |  |  | sub _toxml { | 
| 203 |  |  |  |  |  |  | my ($tag,$attr,$contents) = @_; | 
| 204 |  |  |  |  |  |  | if (defined($contents) && $contents ne "") { | 
| 205 |  |  |  |  |  |  | return _start_tag($tag,$attr) . $contents . _close_tag($tag); | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  | else { | 
| 208 |  |  |  |  |  |  | return _empty_tag($tag,$attr); | 
| 209 |  |  |  |  |  |  | } | 
| 210 |  |  |  |  |  |  | } | 
| 211 |  |  |  |  |  |  |  | 
| 212 |  |  |  |  |  |  | sub _go_down { | 
| 213 |  |  |  |  |  |  | my ($tags, @values) = @_; | 
| 214 |  |  |  |  |  |  | my $tag = shift @$tags; | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  | if (@$tags) { | 
| 217 |  |  |  |  |  |  | join("", | 
| 218 |  |  |  |  |  |  | map { | 
| 219 |  |  |  |  |  |  | my $attrs = {}; | 
| 220 |  |  |  |  |  |  | if (ref($_->[0]) eq 'HASH') { | 
| 221 |  |  |  |  |  |  | $attrs = _clean_attrs(shift @$_); | 
| 222 |  |  |  |  |  |  | } | 
| 223 |  |  |  |  |  |  | _xml_from($tag,$attrs,_go_down([@$tags],@$_)) } ### REALLY NEED TO COPY | 
| 224 |  |  |  |  |  |  | @values) | 
| 225 |  |  |  |  |  |  | } else { | 
| 226 |  |  |  |  |  |  | join("", | 
| 227 |  |  |  |  |  |  | map { _xml_from($tag,{},$_) } @values) | 
| 228 |  |  |  |  |  |  | } | 
| 229 |  |  |  |  |  |  | } | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | sub AUTOLOAD { | 
| 232 |  |  |  |  |  |  | my $attrs = {}; | 
| 233 |  |  |  |  |  |  | my $tag = our $AUTOLOAD; | 
| 234 |  |  |  |  |  |  |  | 
| 235 |  |  |  |  |  |  | $tag =~ s!${MODULENAME}::!!; | 
| 236 |  |  |  |  |  |  |  | 
| 237 |  |  |  |  |  |  | $attrs = shift if ref($_[0]) eq "HASH"; | 
| 238 |  |  |  |  |  |  | $attrs = _clean_attrs($attrs); | 
| 239 |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | if (exists($PTAGS{$tag})) { | 
| 241 |  |  |  |  |  |  | my @tags = @{$PTAGS{$tag}}; | 
| 242 |  |  |  |  |  |  | my $toptag = shift @tags; | 
| 243 |  |  |  |  |  |  | return _xml_from($toptag, $attrs, | 
| 244 |  |  |  |  |  |  | _go_down(\@tags, @_)); | 
| 245 |  |  |  |  |  |  | } | 
| 246 |  |  |  |  |  |  | else { | 
| 247 |  |  |  |  |  |  | if ($tag =~ m/^end_(.*)$/) { | 
| 248 |  |  |  |  |  |  | return _close_tag($1)."\n"; | 
| 249 |  |  |  |  |  |  | } | 
| 250 |  |  |  |  |  |  | elsif ($tag =~ m/^start_(.*)$/) { | 
| 251 |  |  |  |  |  |  | return _start_tag($1, $attrs)."\n"; | 
| 252 |  |  |  |  |  |  | } | 
| 253 |  |  |  |  |  |  | else { | 
| 254 |  |  |  |  |  |  | return _xml_from($tag,$attrs,@_); | 
| 255 |  |  |  |  |  |  | } | 
| 256 |  |  |  |  |  |  | } | 
| 257 |  |  |  |  |  |  | } | 
| 258 |  |  |  |  |  |  |  | 
| 259 |  |  |  |  |  |  | sub quote_entities { | 
| 260 |  |  |  |  |  |  | my $s = shift; | 
| 261 |  |  |  |  |  |  | $s =~ s/&/&/g; | 
| 262 |  |  |  |  |  |  | $s =~ s/</g; | 
| 263 |  |  |  |  |  |  | $s =~ s/>/>/g; | 
| 264 |  |  |  |  |  |  | return $s; | 
| 265 |  |  |  |  |  |  | } | 
| 266 |  |  |  |  |  |  |  | 
| 267 |  |  |  |  |  |  | sub _quote_attr { | 
| 268 |  |  |  |  |  |  | my $s = shift; | 
| 269 |  |  |  |  |  |  | $s =~ s/&/&/g; | 
| 270 |  |  |  |  |  |  | $s =~ s/"/"/g; | 
| 271 |  |  |  |  |  |  | return $s; | 
| 272 |  |  |  |  |  |  | } | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | sub _attributes { | 
| 275 |  |  |  |  |  |  | my $attr = shift; | 
| 276 |  |  |  |  |  |  | return join(" ", map { "$_=\"" . _quote_attr($attr->{$_}) . "\""} keys %$attr); | 
| 277 |  |  |  |  |  |  | } | 
| 278 |  |  |  |  |  |  |  | 
| 279 |  |  |  |  |  |  | sub _start_tag { | 
| 280 |  |  |  |  |  |  | my ($tag, $attr) = @_; | 
| 281 |  |  |  |  |  |  | $tag = "tr" if $tag eq "Tr" && $IS_HTML; | 
| 282 |  |  |  |  |  |  | $attr = _attributes($attr); | 
| 283 |  |  |  |  |  |  | if ($attr) { | 
| 284 |  |  |  |  |  |  | return "<$tag $attr>" | 
| 285 |  |  |  |  |  |  | } else { | 
| 286 |  |  |  |  |  |  | return "<$tag>" | 
| 287 |  |  |  |  |  |  | } | 
| 288 |  |  |  |  |  |  | } | 
| 289 |  |  |  |  |  |  |  | 
| 290 |  |  |  |  |  |  | sub _empty_tag { | 
| 291 |  |  |  |  |  |  | my ($tag, $attr) = @_; | 
| 292 |  |  |  |  |  |  | $tag = "tr" if $tag eq "Tr" && $IS_HTML; | 
| 293 |  |  |  |  |  |  | $attr = _attributes($attr); | 
| 294 |  |  |  |  |  |  | if ($attr) { | 
| 295 |  |  |  |  |  |  | return "<$tag $attr/>" | 
| 296 |  |  |  |  |  |  | } else { | 
| 297 |  |  |  |  |  |  | return "<$tag/>" | 
| 298 |  |  |  |  |  |  | } | 
| 299 |  |  |  |  |  |  | } | 
| 300 |  |  |  |  |  |  |  | 
| 301 |  |  |  |  |  |  | sub _close_tag { | 
| 302 |  |  |  |  |  |  | my $tag = shift; | 
| 303 |  |  |  |  |  |  | $tag = "tr" if $tag eq "Tr" && $IS_HTML; | 
| 304 |  |  |  |  |  |  | return "$tag>"; | 
| 305 |  |  |  |  |  |  | } | 
| 306 |  |  |  |  |  |  |  | 
| 307 |  |  |  |  |  |  |  | 
| 308 |  |  |  |  |  |  | sub import { | 
| 309 |  |  |  |  |  |  | my $class = shift; | 
| 310 |  |  |  |  |  |  |  | 
| 311 |  |  |  |  |  |  | my @tags; | 
| 312 |  |  |  |  |  |  | my @ptags; | 
| 313 |  |  |  |  |  |  | while ($_[0] && $_[0] =~ m!^:(.*)$!) { | 
| 314 |  |  |  |  |  |  | shift; | 
| 315 |  |  |  |  |  |  | my $pack = $1; | 
| 316 |  |  |  |  |  |  | $IS_HTML = 1 if $pack eq "html"; | 
| 317 |  |  |  |  |  |  | if (exists($TAG_SET{$pack})) { | 
| 318 |  |  |  |  |  |  | push @tags  => exists $TAG_SET{$pack}{tags}  ? @{$TAG_SET{$pack}{tags}}  : (); | 
| 319 |  |  |  |  |  |  | push @ptags => exists $TAG_SET{$pack}{ptags} ? @{$TAG_SET{$pack}{ptags}} : (); | 
| 320 |  |  |  |  |  |  | } else { | 
| 321 |  |  |  |  |  |  | die "XML::Writer::Simple - Unknown tagset :$pack\n"; | 
| 322 |  |  |  |  |  |  | } | 
| 323 |  |  |  |  |  |  | } | 
| 324 |  |  |  |  |  |  |  | 
| 325 |  |  |  |  |  |  | my %opts  = @_; | 
| 326 |  |  |  |  |  |  |  | 
| 327 |  |  |  |  |  |  | if (exists($opts{tags})) { | 
| 328 |  |  |  |  |  |  | if (ref($opts{tags}) eq "ARRAY") { | 
| 329 |  |  |  |  |  |  | push @tags   => @{$opts{tags}}; | 
| 330 |  |  |  |  |  |  | } | 
| 331 |  |  |  |  |  |  | } | 
| 332 |  |  |  |  |  |  |  | 
| 333 |  |  |  |  |  |  | if (exists($opts{xml})) { | 
| 334 |  |  |  |  |  |  | my @xmls = (ref($opts{xml}) eq "ARRAY")?@{$opts{xml}}:($opts{xml}); | 
| 335 |  |  |  |  |  |  | my $tags; | 
| 336 |  |  |  |  |  |  | for my $xml (@xmls) { | 
| 337 |  |  |  |  |  |  | dt($xml, -default => sub { $tags->{$q}++ }); | 
| 338 |  |  |  |  |  |  | } | 
| 339 |  |  |  |  |  |  | push @tags   => keys %$tags; | 
| 340 |  |  |  |  |  |  | } | 
| 341 |  |  |  |  |  |  |  | 
| 342 |  |  |  |  |  |  | if (exists($opts{dtd})) { | 
| 343 |  |  |  |  |  |  | my $DTD = ParseDTDFile($opts{dtd}); | 
| 344 |  |  |  |  |  |  | push @tags   => keys %$DTD; | 
| 345 |  |  |  |  |  |  | } | 
| 346 |  |  |  |  |  |  |  | 
| 347 |  |  |  |  |  |  | push @EXPORT => @tags; | 
| 348 |  |  |  |  |  |  | if (exists($opts{partial})) { | 
| 349 |  |  |  |  |  |  | push @EXPORT => map { "start_$_" } @tags; | 
| 350 |  |  |  |  |  |  | push @EXPORT => map { "end_$_"   } @tags; | 
| 351 |  |  |  |  |  |  | } | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | if (@ptags || exists($opts{powertags})) { | 
| 354 |  |  |  |  |  |  | push @ptags => @{$opts{powertags}} if exists $opts{powertags}; | 
| 355 |  |  |  |  |  |  | @PTAGS{@ptags} = map { [split/_/] } @ptags; | 
| 356 |  |  |  |  |  |  | push @EXPORT => @ptags; | 
| 357 |  |  |  |  |  |  | } | 
| 358 |  |  |  |  |  |  |  | 
| 359 |  |  |  |  |  |  | XML::Writer::Simple->export_to_level(1, $class, @EXPORT); | 
| 360 |  |  |  |  |  |  | } | 
| 361 |  |  |  |  |  |  |  | 
| 362 |  |  |  |  |  |  | =head1 AUTHOR | 
| 363 |  |  |  |  |  |  |  | 
| 364 |  |  |  |  |  |  | Alberto Simões, C<<  >> | 
| 365 |  |  |  |  |  |  |  | 
| 366 |  |  |  |  |  |  | =head1 BUGS | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | Please report any bugs or feature requests to | 
| 369 |  |  |  |  |  |  | C, or through the web interface at | 
| 370 |  |  |  |  |  |  | L. | 
| 371 |  |  |  |  |  |  | I will be notified, and then you'll automatically be notified of progress on | 
| 372 |  |  |  |  |  |  | your bug as I make changes. | 
| 373 |  |  |  |  |  |  |  | 
| 374 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 375 |  |  |  |  |  |  |  | 
| 376 |  |  |  |  |  |  | Copyright 1999-2012 Project Natura. | 
| 377 |  |  |  |  |  |  |  | 
| 378 |  |  |  |  |  |  | This library is free software; you can redistribute it and/or modify | 
| 379 |  |  |  |  |  |  | it under the same terms as Perl itself. | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | =cut | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | 1; # End of XML::Writer::Simple |