File Coverage

blib/lib/XML/Simple.pm
Criterion Covered Total %
statement 651 683 95.3
branch 406 452 89.8
condition 97 126 76.9
subroutine 47 48 97.9
pod 14 39 35.9
total 1215 1348 90.1


line stmt bran cond sub pod time code
1             package XML::Simple;
2             $XML::Simple::VERSION = '2.24';
3             =head1 NAME
4              
5             XML::Simple - An API for simple XML files
6              
7             =head1 SYNOPSIS
8              
9             You really don't want to use this module in new code. If you ignore this
10             warning and use it anyway, the C mode will save you a little pain.
11              
12             use XML::Simple qw(:strict);
13              
14             my $ref = XMLin([] [, ]);
15              
16             my $xml = XMLout($hashref [, ]);
17              
18             Or the object oriented way:
19              
20             require XML::Simple qw(:strict);
21              
22             my $xs = XML::Simple->new([]);
23              
24             my $ref = $xs->XMLin([] [, ]);
25              
26             my $xml = $xs->XMLout($hashref [, ]);
27              
28             (or see L<"SAX SUPPORT"> for 'the SAX way').
29              
30             Note, in these examples, the square brackets are used to denote optional items
31             not to imply items should be supplied in arrayrefs.
32              
33             =cut
34              
35             # See after __END__ for more POD documentation
36              
37              
38             # Load essentials here, other modules loaded on demand later
39              
40 12     12   262142 use strict;
  12         18  
  12         290  
41 12     12   44 use warnings;
  12         15  
  12         278  
42 12     12   50 use warnings::register;
  12         10  
  12         1230  
43 12     12   43 use Carp;
  12         12  
  12         635  
44 12     12   42 use Scalar::Util qw();
  12         11  
  12         277  
45             require Exporter;
46              
47              
48             ##############################################################################
49             # Define some constants
50             #
51              
52 12     12   38 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $PREFERRED_PARSER);
  12         12  
  12         75067  
53              
54             @ISA = qw(Exporter);
55             @EXPORT = qw(XMLin XMLout);
56             @EXPORT_OK = qw(xml_in xml_out);
57              
58             my %StrictMode = ();
59              
60             my @KnownOptIn = qw(keyattr keeproot forcecontent contentkey noattr
61             searchpath forcearray cache suppressempty parseropts
62             grouptags nsexpand datahandler varattr variables
63             normalisespace normalizespace valueattr strictmode);
64              
65             my @KnownOptOut = qw(keyattr keeproot contentkey noattr
66             rootname xmldecl outputfile noescape suppressempty
67             grouptags nsexpand handler noindent attrindent nosort
68             valueattr numericescape strictmode);
69              
70             my @DefKeyAttr = qw(name key id);
71             my $DefRootName = qq(opt);
72             my $DefContentKey = qq(content);
73             my $DefXmlDecl = qq();
74              
75             my $xmlns_ns = 'http://www.w3.org/2000/xmlns/';
76             my $bad_def_ns_jcn = '{' . $xmlns_ns . '}'; # LibXML::SAX workaround
77              
78              
79             ##############################################################################
80             # Globals for use by caching routines
81             #
82              
83             my %MemShareCache = ();
84             my %MemCopyCache = ();
85              
86              
87             ##############################################################################
88             # Wrapper for Exporter - handles ':strict'
89             #
90              
91             sub import {
92             # Handle the :strict tag
93              
94 11     11   302 my($calling_package) = caller();
95 11 100       62 _strict_mode_for_caller(1) if grep(/^:strict$/, @_);
96              
97             # Pass everything else to Exporter.pm
98              
99 11         27 @_ = grep(!/^:strict$/, @_);
100 11         14554 goto &Exporter::import;
101             }
102              
103              
104             ##############################################################################
105             # Constructor for optional object interface.
106             #
107              
108             sub new {
109 271     271 0 17128 my $class = shift;
110              
111 271 100       608 if(@_ % 2) {
112 1         138 croak "Default options must be name=>value pairs (odd number supplied)";
113             }
114              
115 270         282 my %known_opt;
116 270         2515 @known_opt{@KnownOptIn, @KnownOptOut} = ();
117              
118 270         357 my %raw_opt = @_;
119             $raw_opt{strictmode} = _strict_mode_for_caller()
120 270 50       722 unless exists $raw_opt{strictmode};
121 270         217 my %def_opt;
122 270         705 while(my($key, $val) = each %raw_opt) {
123 308         367 my $lkey = lc($key);
124 308         475 $lkey =~ s/_//g;
125 308 100       564 croak "Unrecognised option: $key" unless(exists($known_opt{$lkey}));
126 307         815 $def_opt{$lkey} = $val;
127             }
128 269         490 my $self = { def_opt => \%def_opt };
129              
130 269         934 return(bless($self, $class));
131             }
132              
133              
134             ##############################################################################
135             # Sub: _strict_mode_for_caller()
136             #
137             # Gets or sets the XML::Simple :strict mode flag for the calling namespace.
138             # Walks back through call stack to find the calling namespace and sets the
139             # :strict mode flag for that namespace if an argument was supplied and returns
140             # the flag value if not.
141             #
142              
143             sub _strict_mode_for_caller {
144 271     271   255 my $set_mode = @_;
145 271         219 my $frame = 1;
146 271         1707 while(my($package) = caller($frame++)) {
147 757 100       2476 next if $package eq 'XML::Simple';
148 271 100       422 $StrictMode{$package} = 1 if $set_mode;
149 271         627 return $StrictMode{$package};
150             }
151 0         0 return(0);
152             }
153              
154              
155             ##############################################################################
156             # Sub: _get_object()
157             #
158             # Helper routine called from XMLin() and XMLout() to create an object if none
159             # was provided. Note, this routine does mess with the caller's @_ array.
160             #
161              
162             sub _get_object {
163 446     446   400 my $self;
164 446 100 100     3317 if($_[0] and UNIVERSAL::isa($_[0], 'XML::Simple')) {
165 203         192 $self = shift;
166             }
167             else {
168 243         504 $self = XML::Simple->new();
169             }
170              
171 446         428 return $self;
172             }
173              
174              
175             ##############################################################################
176             # Sub/Method: XMLin()
177             #
178             # Exported routine for slurping XML into a hashref - see pod for info.
179             #
180             # May be called as object method or as a plain function.
181             #
182             # Expects one arg for the source XML, optionally followed by a number of
183             # name => value option pairs.
184             #
185              
186             sub XMLin {
187 180     180 1 10147544 my $self = &_get_object; # note, @_ is passed implicitly
188              
189 180         180 my $target = shift;
190              
191              
192             # Work out whether to parse a string, a file or a filehandle
193              
194 180 100       1059 if(not defined $target) {
    100          
    100          
    100          
195 1         3 return $self->parse_file(undef, @_);
196             }
197              
198             elsif($target eq '-') {
199 2         8 local($/) = undef;
200 2         33 $target = ;
201 2         8 return $self->parse_string(\$target, @_);
202             }
203              
204             elsif(my $type = ref($target)) {
205 2 50       9 if($type eq 'SCALAR') {
206 0         0 return $self->parse_string($target, @_);
207             }
208             else {
209 2         7 return $self->parse_fh($target, @_);
210             }
211             }
212              
213             elsif($target =~ m{<.*?>}s) {
214 147         311 return $self->parse_string(\$target, @_);
215             }
216              
217             else {
218 28         82 return $self->parse_file($target, @_);
219             }
220             }
221              
222              
223             ##############################################################################
224             # Sub/Method: parse_file()
225             #
226             # Same as XMLin, but only parses from a named file.
227             #
228              
229             sub parse_file {
230 29     29 1 43 my $self = &_get_object; # note, @_ is passed implicitly
231              
232 29         39 my $filename = shift;
233              
234 29         75 $self->handle_options('in', @_);
235              
236 27 100       57 $filename = $self->default_config_file if not defined $filename;
237              
238 27         34 $filename = $self->find_xml_file($filename, @{$self->{opt}->{searchpath}});
  27         80  
239              
240             # Check cache for previous parse
241              
242 24 100       65 if($self->{opt}->{cache}) {
243 17         20 foreach my $scheme (@{$self->{opt}->{cache}}) {
  17         81  
244 17         26 my $method = 'cache_read_' . $scheme;
245 17         50 my $opt = $self->$method($filename);
246 17 100       352 return($opt) if($opt);
247             }
248             }
249              
250 16         47 my $ref = $self->build_simple_tree($filename, undef);
251              
252 16 100       45 if($self->{opt}->{cache}) {
253 9         23 my $method = 'cache_write_' . $self->{opt}->{cache}->[0];
254 9         31 $self->$method($ref, $filename);
255             }
256              
257 16         1286 return $ref;
258             }
259              
260              
261             ##############################################################################
262             # Sub/Method: parse_fh()
263             #
264             # Same as XMLin, but only parses from a filehandle.
265             #
266              
267             sub parse_fh {
268 2     2 1 3 my $self = &_get_object; # note, @_ is passed implicitly
269              
270 2         3 my $fh = shift;
271 2 0       6 croak "Can't use " . (defined $fh ? qq{string ("$fh")} : 'undef') .
    50          
272             " as a filehandle" unless ref $fh;
273              
274 2         11 $self->handle_options('in', @_);
275              
276 2         6 return $self->build_simple_tree(undef, $fh);
277             }
278              
279              
280             ##############################################################################
281             # Sub/Method: parse_string()
282             #
283             # Same as XMLin, but only parses from a string or a reference to a string.
284             #
285              
286             sub parse_string {
287 149     149 1 170 my $self = &_get_object; # note, @_ is passed implicitly
288              
289 149         122 my $string = shift;
290              
291 149         280 $self->handle_options('in', @_);
292              
293 136 50       336 return $self->build_simple_tree(undef, ref $string ? $string : \$string);
294             }
295              
296              
297             ##############################################################################
298             # Method: default_config_file()
299             #
300             # Returns the name of the XML file to parse if no filename (or XML string)
301             # was provided.
302             #
303              
304             sub default_config_file {
305 1     1 1 2 my $self = shift;
306              
307 1         6 require File::Basename;
308              
309 1         54 my($basename, $script_dir, $ext) = File::Basename::fileparse($0, '\.[^\.]+');
310              
311             # Add script directory to searchpath
312              
313 1 50       3 if($script_dir) {
314 1         1 unshift(@{$self->{opt}->{searchpath}}, $script_dir);
  1         4  
315             }
316              
317 1         2 return $basename . '.xml';
318             }
319              
320              
321             ##############################################################################
322             # Method: build_simple_tree()
323             #
324             # Builds a 'tree' data structure as provided by XML::Parser and then
325             # 'simplifies' it as specified by the various options in effect.
326             #
327              
328             sub build_simple_tree {
329 154     154 1 135 my $self = shift;
330              
331 154         159 my $tree = eval {
332 154         282 $self->build_tree(@_);
333             };
334 154 50       354 Carp::croak("$@XML::Simple called") if $@;
335              
336             return $self->{opt}->{keeproot}
337             ? $self->collapse({}, @$tree)
338 154 100       274 : $self->collapse(@{$tree->[1]});
  149         428  
339             }
340              
341              
342             ##############################################################################
343             # Method: build_tree()
344             #
345             # This routine will be called if there is no suitable pre-parsed tree in a
346             # cache. It parses the XML and returns an XML::Parser 'Tree' style data
347             # structure (summarised in the comments for the collapse() routine below).
348             #
349             # XML::Simple requires the services of another module that knows how to parse
350             # XML. If XML::SAX is installed, the default SAX parser will be used,
351             # otherwise XML::Parser will be used.
352             #
353             # This routine expects to be passed a filename as argument 1 or a 'string' as
354             # argument 2. The 'string' might be a string of XML (passed by reference to
355             # save memory) or it might be a reference to an IO::Handle. (This
356             # non-intuitive mess results in part from the way XML::Parser works but that's
357             # really no excuse).
358             #
359              
360             sub build_tree {
361 154     154 0 132 my $self = shift;
362 154         121 my $filename = shift;
363 154         115 my $string = shift;
364              
365              
366 154         125 my $preferred_parser = $PREFERRED_PARSER;
367 154 100       249 unless(defined($preferred_parser)) {
368 147   50     482 $preferred_parser = $ENV{XML_SIMPLE_PREFERRED_PARSER} || '';
369             }
370 154 50       237 if($preferred_parser eq 'XML::Parser') {
371 0         0 return($self->build_tree_xml_parser($filename, $string));
372             }
373              
374 154         126 eval { require XML::SAX; }; # We didn't need it until now
  154         3929  
375 154 50       29592 if($@) { # No XML::SAX - fall back to XML::Parser
376 0 0       0 if($preferred_parser) { # unless a SAX parser was expressly requested
377 0         0 croak "XMLin() could not load XML::SAX";
378             }
379 0         0 return($self->build_tree_xml_parser($filename, $string));
380             }
381              
382 154 50       210 $XML::SAX::ParserPackage = $preferred_parser if($preferred_parser);
383              
384 154         1046 my $sp = XML::SAX::ParserFactory->parser(Handler => $self);
385              
386 154         521434 $self->{nocollapse} = 1;
387 154         154 my($tree);
388 154 100       237 if($filename) {
389 16         101 $tree = $sp->parse_uri($filename);
390             }
391             else {
392 138 100 66     545 if(ref($string) && ref($string) ne 'SCALAR') {
393 2         14 $tree = $sp->parse_file($string);
394             }
395             else {
396 136         334 $tree = $sp->parse_string($$string);
397             }
398             }
399              
400 154         1399 return($tree);
401             }
402              
403              
404             ##############################################################################
405             # Method: build_tree_xml_parser()
406             #
407             # This routine will be called if XML::SAX is not installed, or if XML::Parser
408             # was specifically requested. It takes the same arguments as build_tree() and
409             # returns the same data structure (XML::Parser 'Tree' style).
410             #
411              
412             sub build_tree_xml_parser {
413 0     0 0 0 my $self = shift;
414 0         0 my $filename = shift;
415 0         0 my $string = shift;
416              
417              
418 0         0 eval {
419 0         0 local($^W) = 0; # Suppress warning from Expat.pm re File::Spec::load()
420 0         0 require XML::Parser; # We didn't need it until now
421             };
422 0 0       0 if($@) {
423 0         0 croak "XMLin() requires either XML::SAX or XML::Parser";
424             }
425              
426 0 0       0 if($self->{opt}->{nsexpand}) {
427 0         0 carp "'nsexpand' option requires XML::SAX";
428             }
429              
430 0         0 my $xp = XML::Parser->new(Style => 'Tree', @{$self->{opt}->{parseropts}});
  0         0  
431 0         0 my($tree);
432 0 0       0 if($filename) {
433             # $tree = $xp->parsefile($filename); # Changed due to prob w/mod_perl
434 0 0       0 open(my $xfh, '<', $filename) || croak qq($filename - $!);
435 0         0 $tree = $xp->parse($xfh);
436             }
437             else {
438 0         0 $tree = $xp->parse($$string);
439             }
440              
441 0         0 return($tree);
442             }
443              
444              
445             ##############################################################################
446             # Method: cache_write_storable()
447             #
448             # Wrapper routine for invoking Storable::nstore() to cache a parsed data
449             # structure.
450             #
451              
452             sub cache_write_storable {
453 5     5 0 9 my($self, $data, $filename) = @_;
454              
455 5         9 my $cachefile = $self->storable_filename($filename);
456              
457 5         51 require Storable; # We didn't need it until now
458              
459 5 50       17 if ('VMS' eq $^O) {
460 0         0 Storable::nstore($data, $cachefile);
461             }
462             else {
463             # If the following line fails for you, your Storable.pm is old - upgrade
464 5         24 Storable::lock_nstore($data, $cachefile);
465             }
466              
467             }
468              
469              
470             ##############################################################################
471             # Method: cache_read_storable()
472             #
473             # Wrapper routine for invoking Storable::retrieve() to read a cached parsed
474             # data structure. Only returns cached data if the cache file exists and is
475             # newer than the source XML file.
476             #
477              
478             sub cache_read_storable {
479 8     8 0 9 my($self, $filename) = @_;
480              
481 8         26 my $cachefile = $self->storable_filename($filename);
482              
483 8 100       83 return unless(-r $cachefile);
484 6 100       68 return unless((stat($cachefile))[9] > (stat($filename))[9]);
485              
486 3         12 require Storable; # We didn't need it until now
487              
488 3 50       15 if ('VMS' eq $^O) {
489 0         0 return(Storable::retrieve($cachefile));
490             }
491             else {
492 3         15 return(Storable::lock_retrieve($cachefile));
493             }
494              
495             }
496              
497              
498             ##############################################################################
499             # Method: storable_filename()
500             #
501             # Translates the supplied source XML filename into a filename for the storable
502             # cached data. A '.stor' suffix is added after stripping an optional '.xml'
503             # suffix.
504             #
505              
506             sub storable_filename {
507 12     12 0 248 my($self, $cachefile) = @_;
508              
509 12         58 $cachefile =~ s{(\.xml)?$}{.stor};
510 12         24 return $cachefile;
511             }
512              
513              
514             ##############################################################################
515             # Method: cache_write_memshare()
516             #
517             # Takes the supplied data structure reference and stores it away in a global
518             # hash structure.
519             #
520              
521             sub cache_write_memshare {
522 2     2 0 3 my($self, $data, $filename) = @_;
523              
524 2         6 $MemShareCache{$filename} = [time(), $data];
525             }
526              
527              
528             ##############################################################################
529             # Method: cache_read_memshare()
530             #
531             # Takes a filename and looks in a global hash for a cached parsed version.
532             #
533              
534             sub cache_read_memshare {
535 4     4 0 6 my($self, $filename) = @_;
536              
537 4 100       11 return unless($MemShareCache{$filename});
538 3 100       28 return unless($MemShareCache{$filename}->[0] > (stat($filename))[9]);
539              
540 2         4 return($MemShareCache{$filename}->[1]);
541              
542             }
543              
544              
545             ##############################################################################
546             # Method: cache_write_memcopy()
547             #
548             # Takes the supplied data structure and stores a copy of it in a global hash
549             # structure.
550             #
551              
552             sub cache_write_memcopy {
553 2     2 0 4 my($self, $data, $filename) = @_;
554              
555 2         15 require Storable; # We didn't need it until now
556              
557 2         126 $MemCopyCache{$filename} = [time(), Storable::dclone($data)];
558             }
559              
560              
561             ##############################################################################
562             # Method: cache_read_memcopy()
563             #
564             # Takes a filename and looks in a global hash for a cached parsed version.
565             # Returns a reference to a copy of that data structure.
566             #
567              
568             sub cache_read_memcopy {
569 4     4 0 4 my($self, $filename) = @_;
570              
571 4 100       11 return unless($MemCopyCache{$filename});
572 3 100       27 return unless($MemCopyCache{$filename}->[0] > (stat($filename))[9]);
573              
574 2         48 return(Storable::dclone($MemCopyCache{$filename}->[1]));
575              
576             }
577              
578              
579             ##############################################################################
580             # Sub/Method: XMLout()
581             #
582             # Exported routine for 'unslurping' a data structure out to XML.
583             #
584             # Expects a reference to a data structure and an optional list of option
585             # name => value pairs.
586             #
587              
588             sub XMLout {
589 86     86 1 43099 my $self = &_get_object; # note, @_ is passed implicitly
590              
591 86 100       444 croak "XMLout() requires at least one argument" unless(@_);
592 84         89 my $ref = shift;
593              
594 84         148 $self->handle_options('out', @_);
595              
596              
597             # If namespace expansion is set, XML::NamespaceSupport is required
598              
599 79 100       127 if($self->{opt}->{nsexpand}) {
600 3         13 require XML::NamespaceSupport;
601 3         9 $self->{nsup} = XML::NamespaceSupport->new();
602 3         29 $self->{ns_prefix} = 'aaa';
603             }
604              
605              
606             # Wrap top level arrayref in a hash
607              
608 79 100       175 if(UNIVERSAL::isa($ref, 'ARRAY')) {
609 4         8 $ref = { anon => $ref };
610             }
611              
612              
613             # Extract rootname from top level hash if keeproot enabled
614              
615 79 100       183 if($self->{opt}->{keeproot}) {
    100          
616 2         8 my(@keys) = keys(%$ref);
617 2 50       7 if(@keys == 1) {
618 2         4 $ref = $ref->{$keys[0]};
619 2         4 $self->{opt}->{rootname} = $keys[0];
620             }
621             }
622              
623             # Ensure there are no top level attributes if we're not adding root elements
624              
625             elsif($self->{opt}->{rootname} eq '') {
626 5 100       12 if(UNIVERSAL::isa($ref, 'HASH')) {
627 3         4 my $refsave = $ref;
628 3         3 $ref = {};
629 3         6 foreach (keys(%$refsave)) {
630 7 100       10 if(ref($refsave->{$_})) {
631 3         5 $ref->{$_} = $refsave->{$_};
632             }
633             else {
634 4         7 $ref->{$_} = [ $refsave->{$_} ];
635             }
636             }
637             }
638             }
639              
640              
641             # Encode the hashref and write to file if necessary
642              
643 79         91 $self->{_ancestors} = {};
644 79         161 my $xml = $self->value_to_xml($ref, $self->{opt}->{rootname}, '');
645 77         116 delete $self->{_ancestors};
646              
647 77 100       122 if($self->{opt}->{xmldecl}) {
648 2         5 $xml = $self->{opt}->{xmldecl} . "\n" . $xml;
649             }
650              
651 77 100       149 if($self->{opt}->{outputfile}) {
    100          
652 2 100       4 if(ref($self->{opt}->{outputfile})) {
653 1         2 my $fh = $self->{opt}->{outputfile};
654 1 50 33     15 if(UNIVERSAL::isa($fh, 'GLOB') and !UNIVERSAL::can($fh, 'print')) {
655 0         0 eval { require IO::Handle; };
  0         0  
656 0 0       0 croak $@ if $@;
657             }
658 1         4 return($fh->print($xml));
659             }
660             else {
661 1 50       59 open(my $out, '>', "$self->{opt}->{outputfile}") ||
662             croak "open($self->{opt}->{outputfile}): $!";
663 1 50       8 binmode($out, ':utf8') if($] >= 5.008);
664 1 50       11 print $out $xml or croak "print: $!";
665 1 50       32 close $out or croak "close: $!";
666             }
667             }
668             elsif($self->{opt}->{handler}) {
669 2         10 require XML::SAX;
670             my $sp = XML::SAX::ParserFactory->parser(
671             Handler => $self->{opt}->{handler}
672 2         11 );
673 2         447 return($sp->parse_string($xml));
674             }
675             else {
676 73         334 return($xml);
677             }
678             }
679              
680              
681             ##############################################################################
682             # Method: handle_options()
683             #
684             # Helper routine for both XMLin() and XMLout(). Both routines handle their
685             # first argument and assume all other args are options handled by this routine.
686             # Saves a hash of options in $self->{opt}.
687             #
688             # If default options were passed to the constructor, they will be retrieved
689             # here and merged with options supplied to the method call.
690             #
691             # First argument should be the string 'in' or the string 'out'.
692             #
693             # Remaining arguments should be name=>value pairs. Sets up default values
694             # for options not supplied. Unrecognised options are a fatal error.
695             #
696              
697             sub handle_options {
698 271     271 1 205 my $self = shift;
699 271         221 my $dirn = shift;
700              
701              
702             # Determine valid options based on context
703              
704 271         213 my %known_opt;
705 271 100       362 if($dirn eq 'in') {
706 187         1051 @known_opt{@KnownOptIn} = @KnownOptIn;
707             }
708             else {
709 84         393 @known_opt{@KnownOptOut} = @KnownOptOut;
710             }
711              
712              
713             # Store supplied options in hashref and weed out invalid ones
714              
715 271 100       502 if(@_ % 2) {
716 2         177 croak "Options must be name=>value pairs (odd number supplied)";
717             }
718 269         407 my %raw_opt = @_;
719 269         248 my $opt = {};
720 269         376 $self->{opt} = $opt;
721              
722 269         621 while(my($key, $val) = each %raw_opt) {
723 269         273 my $lkey = lc($key);
724 269         262 $lkey =~ s/_//g;
725 269 100       666 croak "Unrecognised option: $key" unless($known_opt{$lkey});
726 267         711 $opt->{$lkey} = $val;
727             }
728              
729              
730             # Merge in options passed to constructor
731              
732 267         813 foreach (keys(%known_opt)) {
733 4991 100       5395 unless(exists($opt->{$_})) {
734 4724 100       5788 if(exists($self->{def_opt}->{$_})) {
735 314         400 $opt->{$_} = $self->{def_opt}->{$_};
736             }
737             }
738             }
739              
740              
741             # Set sensible defaults if not supplied
742              
743 267 100       512 if(exists($opt->{rootname})) {
744 20 100       35 unless(defined($opt->{rootname})) {
745 1         1 $opt->{rootname} = '';
746             }
747             }
748             else {
749 247         287 $opt->{rootname} = $DefRootName;
750             }
751              
752 267 100 100     511 if($opt->{xmldecl} and $opt->{xmldecl} eq '1') {
753 1         2 $opt->{xmldecl} = $DefXmlDecl;
754             }
755              
756 267 100       339 if(exists($opt->{contentkey})) {
757 69 100       216 if($opt->{contentkey} =~ m{^-(.*)$}) {
758 61         140 $opt->{contentkey} = $1;
759 61         81 $opt->{collapseagain} = 1;
760             }
761             }
762             else {
763 198         191 $opt->{contentkey} = $DefContentKey;
764             }
765              
766 267 100       359 unless(exists($opt->{normalisespace})) {
767 263         291 $opt->{normalisespace} = $opt->{normalizespace};
768             }
769 267 100       453 $opt->{normalisespace} = 0 unless(defined($opt->{normalisespace}));
770              
771             # Cleanups for values assumed to be arrays later
772              
773 267 100       308 if($opt->{searchpath}) {
774 3 100       8 unless(ref($opt->{searchpath})) {
775 2         4 $opt->{searchpath} = [ $opt->{searchpath} ];
776             }
777             }
778             else {
779 264         315 $opt->{searchpath} = [ ];
780             }
781              
782 267 100 100     546 if($opt->{cache} and !ref($opt->{cache})) {
783 18         32 $opt->{cache} = [ $opt->{cache} ];
784             }
785 267 100       400 if($opt->{cache}) {
786 19         19 $_ = lc($_) foreach (@{$opt->{cache}});
  19         66  
787 19         18 foreach my $scheme (@{$opt->{cache}}) {
  19         29  
788 19         34 my $method = 'cache_read_' . $scheme;
789 19 100       417 croak "Unsupported caching scheme: $scheme"
790             unless($self->can($method));
791             }
792             }
793              
794 265 50       319 if(exists($opt->{parseropts})) {
795 0 0       0 if(warnings::enabled()) {
796 0         0 carp "Warning: " .
797             "'ParserOpts' is deprecated, contact the author if you need it";
798             }
799             }
800             else {
801 265         342 $opt->{parseropts} = [ ];
802             }
803              
804              
805             # Special cleanup for {forcearray} which could be regex, arrayref or boolean
806             # or left to default to 0
807              
808 265 100       353 if(exists($opt->{forcearray})) {
809 36 100       79 if(ref($opt->{forcearray}) eq 'Regexp') {
810 1         3 $opt->{forcearray} = [ $opt->{forcearray} ];
811             }
812              
813 36 100       68 if(ref($opt->{forcearray}) eq 'ARRAY') {
814 16         16 my @force_list = @{$opt->{forcearray}};
  16         38  
815 16 100       25 if(@force_list) {
816 14         20 $opt->{forcearray} = {};
817 14         17 foreach my $tag (@force_list) {
818 21 100       33 if(ref($tag) eq 'Regexp') {
819 3         3 push @{$opt->{forcearray}->{_regex}}, $tag;
  3         7  
820             }
821             else {
822 18         44 $opt->{forcearray}->{$tag} = 1;
823             }
824             }
825             }
826             else {
827 2         2 $opt->{forcearray} = 0;
828             }
829             }
830             else {
831 20 100       42 $opt->{forcearray} = ( $opt->{forcearray} ? 1 : 0 );
832             }
833             }
834             else {
835 229 100 100     412 if($opt->{strictmode} and $dirn eq 'in') {
836 3         381 croak "No value specified for 'ForceArray' option in call to XML$dirn()";
837             }
838 226         320 $opt->{forcearray} = 0;
839             }
840              
841              
842             # Special cleanup for {keyattr} which could be arrayref or hashref or left
843             # to default to arrayref
844              
845 262 100       310 if(exists($opt->{keyattr})) {
846 78 100       124 if(ref($opt->{keyattr})) {
847 74 100       124 if(ref($opt->{keyattr}) eq 'HASH') {
848              
849             # Make a copy so we can mess with it
850              
851 58         50 $opt->{keyattr} = { %{$opt->{keyattr}} };
  58         141  
852              
853              
854             # Convert keyattr => { elem => '+attr' }
855             # to keyattr => { elem => [ 'attr', '+' ] }
856              
857 58         56 foreach my $el (keys(%{$opt->{keyattr}})) {
  58         118  
858 64 50       238 if($opt->{keyattr}->{$el} =~ /^(\+|-)?(.*)$/) {
859 64 100       202 $opt->{keyattr}->{$el} = [ $2, ($1 ? $1 : '') ];
860 64 100 100     174 if($opt->{strictmode} and $dirn eq 'in') {
861 9 100       17 next if($opt->{forcearray} == 1);
862             next if(ref($opt->{forcearray}) eq 'HASH'
863 6 100 66     15 and $opt->{forcearray}->{$el});
864 4         356 croak "<$el> set in KeyAttr but not in ForceArray";
865             }
866             }
867             else {
868 0         0 delete($opt->{keyattr}->{$el}); # Never reached (famous last words?)
869             }
870             }
871             }
872             else {
873 16 100       16 if(@{$opt->{keyattr}} == 0) {
  16         320  
874 4         8 delete($opt->{keyattr});
875             }
876             }
877             }
878             else {
879 4         6 $opt->{keyattr} = [ $opt->{keyattr} ];
880             }
881             }
882             else {
883 184 100       275 if($opt->{strictmode}) {
884 4         351 croak "No value specified for 'KeyAttr' option in call to XML$dirn()";
885             }
886 180         378 $opt->{keyattr} = [ @DefKeyAttr ];
887             }
888              
889              
890             # Special cleanup for {valueattr} which could be arrayref or hashref
891              
892 254 100       427 if(exists($opt->{valueattr})) {
893 5 100       12 if(ref($opt->{valueattr}) eq 'ARRAY') {
894 2         3 $opt->{valueattrlist} = {};
895 2         3 $opt->{valueattrlist}->{$_} = 1 foreach(@{ delete $opt->{valueattr} });
  2         7  
896             }
897             }
898              
899             # make sure there's nothing weird in {grouptags}
900              
901 254 100       375 if($opt->{grouptags}) {
902             croak "Illegal value for 'GroupTags' option - expected a hashref"
903 14 100       232 unless UNIVERSAL::isa($opt->{grouptags}, 'HASH');
904              
905 13         11 while(my($key, $val) = each %{$opt->{grouptags}}) {
  27         61  
906 15 100       43 next if $key ne $val;
907 1         142 croak "Bad value in GroupTags: '$key' => '$val'";
908             }
909             }
910              
911              
912             # Check the {variables} option is valid and initialise variables hash
913              
914 252 100 100     464 if($opt->{variables} and !UNIVERSAL::isa($opt->{variables}, 'HASH')) {
915 1         106 croak "Illegal value for 'Variables' option - expected a hashref";
916             }
917              
918 251 100       1008 if($opt->{variables}) {
    100          
919 4         5 $self->{_var_values} = { %{$opt->{variables}} };
  4         21  
920             }
921             elsif($opt->{varattr}) {
922 2         6 $self->{_var_values} = {};
923             }
924              
925             }
926              
927              
928             ##############################################################################
929             # Method: find_xml_file()
930             #
931             # Helper routine for XMLin().
932             # Takes a filename, and a list of directories, attempts to locate the file in
933             # the directories listed.
934             # Returns a full pathname on success; croaks on failure.
935             #
936              
937             sub find_xml_file {
938 27     27 0 33 my $self = shift;
939 27         28 my $file = shift;
940 27         39 my @search_path = @_;
941              
942              
943 27         179 require File::Basename;
944 27         75 require File::Spec;
945              
946 27         634 my($filename, $filedir) = File::Basename::fileparse($file);
947              
948 27 100       63 if($filename ne $file) { # Ignore searchpath if dir component
949 23 100       406 return($file) if(-e $file);
950             }
951             else {
952 4         3 my($path);
953 4         6 foreach $path (@search_path) {
954 5         40 my $fullpath = File::Spec->catfile($path, $file);
955 5 100       99 return($fullpath) if(-e $fullpath);
956             }
957             }
958              
959             # If user did not supply a search path, default to current directory
960              
961 3 100       7 if(!@search_path) {
962 1 50       20 return($file) if(-e $file);
963 1         95 croak "File does not exist: $file";
964             }
965              
966 2         278 croak "Could not find $file in ", join(':', @search_path);
967             }
968              
969              
970             ##############################################################################
971             # Method: collapse()
972             #
973             # Helper routine for XMLin(). This routine really comprises the 'smarts' (or
974             # value add) of this module.
975             #
976             # Takes the parse tree that XML::Parser produced from the supplied XML and
977             # recurses through it 'collapsing' unnecessary levels of indirection (nested
978             # arrays etc) to produce a data structure that is easier to work with.
979             #
980             # Elements in the original parser tree are represented as an element name
981             # followed by an arrayref. The first element of the array is a hashref
982             # containing the attributes. The rest of the array contains a list of any
983             # nested elements as name+arrayref pairs:
984             #
985             # , [ { }, , [ ... ], ... ]
986             #
987             # The special element name '0' (zero) flags text content.
988             #
989             # This routine cuts down the noise by discarding any text content consisting of
990             # only whitespace and then moves the nested elements into the attribute hash
991             # using the name of the nested element as the hash key and the collapsed
992             # version of the nested element as the value. Multiple nested elements with
993             # the same name will initially be represented as an arrayref, but this may be
994             # 'folded' into a hashref depending on the value of the keyattr option.
995             #
996              
997             sub collapse {
998 3537     3537 0 2403 my $self = shift;
999              
1000              
1001             # Start with the hash of attributes
1002              
1003 3537         2280 my $attr = shift;
1004 3537 100       6150 if($self->{opt}->{noattr}) { # Discard if 'noattr' set
    100          
1005 36         40 $attr = $self->new_hashref;
1006             }
1007             elsif($self->{opt}->{normalisespace} == 2) {
1008 15         30 while(my($key, $value) = each %$attr) {
1009 2         5 $attr->{$key} = $self->normalise_space($value)
1010             }
1011             }
1012              
1013              
1014             # Do variable substitutions
1015              
1016 3537 100       4158 if(my $var = $self->{_var_values}) {
1017 37         86 while(my($key, $val) = each(%$attr)) {
1018 30         48 $val =~ s^\$\{([\w.]+)\}^ $self->get_var($1) ^ge;
  4         6  
1019 30         72 $attr->{$key} = $val;
1020             }
1021             }
1022              
1023              
1024             # Roll up 'value' attributes (but only if no nested elements)
1025              
1026 3537 100 100     8369 if(!@_ and keys %$attr == 1) {
1027 42         84 my($k) = keys %$attr;
1028 42 100 66     98 if($self->{opt}->{valueattrlist} and $self->{opt}->{valueattrlist}->{$k}) {
1029 7         11 return $attr->{$k};
1030             }
1031             }
1032              
1033              
1034             # Add any nested elements
1035              
1036 3530         2255 my($key, $val);
1037 3530         4114 while(@_) {
1038 8308         6073 $key = shift;
1039 8308         5849 $val = shift;
1040 8308 50       9317 $val = '' if not defined $val;
1041              
1042 8308 100       11209 if(ref($val)) {
    50          
1043 3376         4307 $val = $self->collapse(@$val);
1044 3376 100 66     4302 next if(!defined($val) and $self->{opt}->{suppressempty});
1045             }
1046             elsif($key eq '0') {
1047 4932 100       11075 next if($val =~ m{^\s*$}s); # Skip all whitespace content
1048              
1049             $val = $self->normalise_space($val)
1050 1268 100       1574 if($self->{opt}->{normalisespace} == 2);
1051              
1052             # do variable substitutions
1053              
1054 1268 100       1522 if(my $var = $self->{_var_values}) {
1055 26         70 $val =~ s^\$\{(\w+)\}^ $self->get_var($1) ^ge;
  17         27  
1056             }
1057              
1058              
1059             # look for variable definitions
1060              
1061 1268 100       1514 if(my $var = $self->{opt}->{varattr}) {
1062 23 100       36 if(exists $attr->{$var}) {
1063 10         16 $self->set_var($attr->{$var}, $val);
1064             }
1065             }
1066              
1067              
1068             # Collapse text content in element with no attributes to a string
1069              
1070 1268 100 66     2679 if(!%$attr and !@_) {
1071             return($self->{opt}->{forcecontent} ?
1072 1141 100       2147 { $self->{opt}->{contentkey} => $val } : $val
1073             );
1074             }
1075 127         155 $key = $self->{opt}->{contentkey};
1076             }
1077              
1078              
1079             # Combine duplicate attributes into arrayref if required
1080              
1081 3497 100 100     6209 if(exists($attr->{$key})) {
    100          
1082 2859 100       4298 if(UNIVERSAL::isa($attr->{$key}, 'ARRAY')) {
1083 2729         1607 push(@{$attr->{$key}}, $val);
  2729         5338  
1084             }
1085             else {
1086 130         338 $attr->{$key} = [ $attr->{$key}, $val ];
1087             }
1088             }
1089             elsif(defined($val) and UNIVERSAL::isa($val, 'ARRAY')) {
1090 4         12 $attr->{$key} = [ $val ];
1091             }
1092             else {
1093 634 100 66     2156 if( $key ne $self->{opt}->{contentkey}
      66        
1094             and (
1095             ($self->{opt}->{forcearray} == 1)
1096             or (
1097             (ref($self->{opt}->{forcearray}) eq 'HASH')
1098             and (
1099             $self->{opt}->{forcearray}->{$key}
1100             or (grep $key =~ $_, @{$self->{opt}->{forcearray}->{_regex}})
1101             )
1102             )
1103             )
1104             ) {
1105 194         484 $attr->{$key} = [ $val ];
1106             }
1107             else {
1108 440         898 $attr->{$key} = $val;
1109             }
1110             }
1111              
1112             }
1113              
1114              
1115             # Turn arrayrefs into hashrefs if key fields present
1116              
1117 2389 100       3103 if($self->{opt}->{keyattr}) {
1118 2367         5128 while(($key,$val) = each %$attr) {
1119 4725 100 100     21023 if(defined($val) and UNIVERSAL::isa($val, 'ARRAY')) {
1120 322         499 $attr->{$key} = $self->array_to_hash($key, $val);
1121             }
1122             }
1123             }
1124              
1125              
1126             # disintermediate grouped tags
1127              
1128 2384 100       3093 if($self->{opt}->{grouptags}) {
1129 26         63 while(my($key, $val) = each(%$attr)) {
1130 51 100 100     183 next unless(UNIVERSAL::isa($val, 'HASH') and (keys %$val == 1));
1131 10 100       21 next unless(exists($self->{opt}->{grouptags}->{$key}));
1132              
1133 9         12 my($child_key, $child_val) = %$val;
1134              
1135 9 100       22 if($self->{opt}->{grouptags}->{$key} eq $child_key) {
1136 8         19 $attr->{$key}= $child_val;
1137             }
1138             }
1139             }
1140              
1141              
1142             # Fold hashes containing a single anonymous array up into just the array
1143              
1144 2384         1889 my $count = scalar keys %$attr;
1145 2384 100 66     3299 if($count == 1
      66        
1146             and exists $attr->{anon}
1147             and UNIVERSAL::isa($attr->{anon}, 'ARRAY')
1148             ) {
1149 61         143 return($attr->{anon});
1150             }
1151              
1152              
1153             # Do the right thing if hash is empty, otherwise just return it
1154              
1155 2323 100 66     2681 if(!%$attr and exists($self->{opt}->{suppressempty})) {
1156 11 100 100     33 if(defined($self->{opt}->{suppressempty}) and
1157             $self->{opt}->{suppressempty} eq '') {
1158 2         4 return('');
1159             }
1160 9         20 return(undef);
1161             }
1162              
1163              
1164             # Roll up named elements with named nested 'value' attributes
1165              
1166 2312 100       2715 if($self->{opt}->{valueattr}) {
1167 10         21 while(my($key, $val) = each(%$attr)) {
1168 18 100       47 next unless($self->{opt}->{valueattr}->{$key});
1169 4 50 33     17 next unless(UNIVERSAL::isa($val, 'HASH') and (keys %$val == 1));
1170 4         5 my($k) = keys %$val;
1171 4 50       7 next unless($k eq $self->{opt}->{valueattr}->{$key});
1172 4         10 $attr->{$key} = $val->{$k};
1173             }
1174             }
1175              
1176 2312         5190 return($attr)
1177              
1178             }
1179              
1180              
1181             ##############################################################################
1182             # Method: set_var()
1183             #
1184             # Called when a variable definition is encountered in the XML. (A variable
1185             # definition looks like value where attrname
1186             # matches the varattr setting).
1187             #
1188              
1189             sub set_var {
1190 10     10 0 12 my($self, $name, $value) = @_;
1191              
1192 10         20 $self->{_var_values}->{$name} = $value;
1193             }
1194              
1195              
1196             ##############################################################################
1197             # Method: get_var()
1198             #
1199             # Called during variable substitution to get the value for the named variable.
1200             #
1201              
1202             sub get_var {
1203 21     21 0 37 my($self, $name) = @_;
1204              
1205 21         26 my $value = $self->{_var_values}->{$name};
1206 21 100       62 return $value if(defined($value));
1207              
1208 1         3 return '${' . $name . '}';
1209             }
1210              
1211              
1212             ##############################################################################
1213             # Method: normalise_space()
1214             #
1215             # Strips leading and trailing whitespace and collapses sequences of whitespace
1216             # characters to a single space.
1217             #
1218              
1219             sub normalise_space {
1220 16     16 0 15 my($self, $text) = @_;
1221              
1222 16         42 $text =~ s/^\s+//s;
1223 16         74 $text =~ s/\s+$//s;
1224 16         40 $text =~ s/\s\s+/ /sg;
1225              
1226 16         27 return $text;
1227             }
1228              
1229              
1230             ##############################################################################
1231             # Method: array_to_hash()
1232             #
1233             # Helper routine for collapse().
1234             # Attempts to 'fold' an array of hashes into an hash of hashes. Returns a
1235             # reference to the hash on success or the original array if folding is
1236             # not possible. Behaviour is controlled by 'keyattr' option.
1237             #
1238              
1239             sub array_to_hash {
1240 322     322 0 255 my $self = shift;
1241 322         243 my $name = shift;
1242 322         212 my $arrayref = shift;
1243              
1244 322         396 my $hashref = $self->new_hashref;
1245              
1246 322         256 my($i, $key, $val, $flag);
1247              
1248              
1249             # Handle keyattr => { .... }
1250              
1251 322 100       514 if(ref($self->{opt}->{keyattr}) eq 'HASH') {
1252 189 100       503 return($arrayref) unless(exists($self->{opt}->{keyattr}->{$name}));
1253 121         94 ($key, $flag) = @{$self->{opt}->{keyattr}->{$name}};
  121         211  
1254 121         210 for($i = 0; $i < @$arrayref; $i++) {
1255 1912 100 33     4184 if(UNIVERSAL::isa($arrayref->[$i], 'HASH') and
1256             exists($arrayref->[$i]->{$key})
1257             ) {
1258 1908         1410 $val = $arrayref->[$i]->{$key};
1259 1908 100       2128 if(ref($val)) {
1260 4         15 $self->die_or_warn("<$name> element has non-scalar '$key' key attribute");
1261 2         48 return($arrayref);
1262             }
1263             $val = $self->normalise_space($val)
1264 1904 100       2216 if($self->{opt}->{normalisespace} == 1);
1265             $self->die_or_warn("<$name> element has non-unique value in '$key' key attribute: $val")
1266 1904 100       2289 if(exists($hashref->{$val}));
1267 1903         1160 $hashref->{$val} = $self->new_hashref( %{$arrayref->[$i]} );
  1903         2976  
1268 1903 100       2681 $hashref->{$val}->{"-$key"} = $hashref->{$val}->{$key} if($flag eq '-');
1269 1903 100       4094 delete $hashref->{$val}->{$key} unless($flag eq '+');
1270             }
1271             else {
1272 4         15 $self->die_or_warn("<$name> element has no '$key' key attribute");
1273 2         42 return($arrayref);
1274             }
1275             }
1276             }
1277              
1278              
1279             # Or assume keyattr => [ .... ]
1280              
1281             else {
1282             my $default_keys =
1283 133         232 join(',', @DefKeyAttr) eq join(',', @{$self->{opt}->{keyattr}});
  133         208  
1284              
1285 133         232 ELEMENT: for($i = 0; $i < @$arrayref; $i++) {
1286 205 100       676 return($arrayref) unless(UNIVERSAL::isa($arrayref->[$i], 'HASH'));
1287              
1288 129         113 foreach $key (@{$self->{opt}->{keyattr}}) {
  129         194  
1289 173 100       249 if(defined($arrayref->[$i]->{$key})) {
1290 119         123 $val = $arrayref->[$i]->{$key};
1291 119 100       170 if(ref($val)) {
1292 2 100       8 $self->die_or_warn("<$name> element has non-scalar '$key' key attribute")
1293             if not $default_keys;
1294 2         58 return($arrayref);
1295             }
1296             $val = $self->normalise_space($val)
1297 117 100       178 if($self->{opt}->{normalisespace} == 1);
1298             $self->die_or_warn("<$name> element has non-unique value in '$key' key attribute: $val")
1299 117 100       184 if(exists($hashref->{$val}));
1300 117         120 $hashref->{$val} = $self->new_hashref( %{$arrayref->[$i]} );
  117         258  
1301 117         176 delete $hashref->{$val}->{$key};
1302 117         231 next ELEMENT;
1303             }
1304             }
1305              
1306 10         26 return($arrayref); # No keyfield matched
1307             }
1308             }
1309              
1310             # collapse any hashes which now only have a 'content' key
1311              
1312 157 100       269 if($self->{opt}->{collapseagain}) {
1313 36         59 $hashref = $self->collapse_content($hashref);
1314             }
1315              
1316 157         434 return($hashref);
1317             }
1318              
1319              
1320             ##############################################################################
1321             # Method: die_or_warn()
1322             #
1323             # Takes a diagnostic message and does one of three things:
1324             # 1. dies if strict mode is enabled
1325             # 2. warns if warnings are enabled but strict mode is not
1326             # 3. ignores message and returns silently if neither strict mode nor warnings
1327             # are enabled
1328             #
1329              
1330             sub die_or_warn {
1331 13     13 0 13 my $self = shift;
1332 13         10 my $msg = shift;
1333              
1334 13 100       586 croak $msg if($self->{opt}->{strictmode});
1335 8 100       620 if(warnings::enabled()) {
1336 5         620 carp "Warning: $msg";
1337             }
1338             }
1339              
1340              
1341             ##############################################################################
1342             # Method: new_hashref()
1343             #
1344             # This is a hook routine for overriding in a sub-class. Some people believe
1345             # that using Tie::IxHash here will solve order-loss problems.
1346             #
1347              
1348             sub new_hashref {
1349 2385     2385 1 1579 my $self = shift;
1350              
1351 2385         4732 return { @_ };
1352             }
1353              
1354              
1355             ##############################################################################
1356             # Method: collapse_content()
1357             #
1358             # Helper routine for array_to_hash
1359             #
1360             # Arguments expected are:
1361             # - an XML::Simple object
1362             # - a hashref
1363             # the hashref is a former array, turned into a hash by array_to_hash because
1364             # of the presence of key attributes
1365             # at this point collapse_content avoids over-complicated structures like
1366             # dir => { libexecdir => { content => '$exec_prefix/libexec' },
1367             # localstatedir => { content => '$prefix' },
1368             # }
1369             # into
1370             # dir => { libexecdir => '$exec_prefix/libexec',
1371             # localstatedir => '$prefix',
1372             # }
1373              
1374             sub collapse_content {
1375 36     36 0 31 my $self = shift;
1376 36         25 my $hashref = shift;
1377              
1378 36         39 my $contentkey = $self->{opt}->{contentkey};
1379              
1380             # first go through the values,checking that they are fit to collapse
1381 36         64 foreach my $val (values %$hashref) {
1382             return $hashref unless ( (ref($val) eq 'HASH')
1383             and (keys %$val == 1)
1384 70 100 66     304 and (exists $val->{$contentkey})
      66        
1385             );
1386             }
1387              
1388             # now collapse them
1389 14         24 foreach my $key (keys %$hashref) {
1390 48         85 $hashref->{$key}= $hashref->{$key}->{$contentkey};
1391             }
1392              
1393 14         22 return $hashref;
1394             }
1395              
1396              
1397             ##############################################################################
1398             # Method: value_to_xml()
1399             #
1400             # Helper routine for XMLout() - recurses through a data structure building up
1401             # and returning an XML representation of that structure as a string.
1402             #
1403             # Arguments expected are:
1404             # - the data structure to be encoded (usually a reference)
1405             # - the XML tag name to use for this item
1406             # - a string of spaces for use as the current indent level
1407             #
1408              
1409             sub value_to_xml {
1410 2186     2186 0 1734 my $self = shift;;
1411              
1412              
1413             # Grab the other arguments
1414              
1415 2186         2000 my($ref, $name, $indent) = @_;
1416              
1417 2186   33     4063 my $named = (defined($name) and $name ne '' ? 1 : 0);
1418              
1419 2186         1557 my $nl = "\n";
1420              
1421 2186 100       2187 my $is_root = $indent eq '' ? 1 : 0; # Warning, dirty hack!
1422 2186 100       2862 if($self->{opt}->{noindent}) {
1423 6         7 $indent = '';
1424 6         7 $nl = '';
1425             }
1426              
1427              
1428             # Convert to XML
1429              
1430 2186         2588 my $refaddr = Scalar::Util::refaddr($ref);
1431 2186 100       2210 if($refaddr) {
1432             croak "circular data structures not supported"
1433 2170 100       3186 if $self->{_ancestors}->{$refaddr};
1434 2169         2856 $self->{_ancestors}->{$refaddr} = $ref; # keep ref alive until we delete it
1435             }
1436             else {
1437 16 100       16 if($named) {
1438             return(join('',
1439             $indent, '<', $name, '>',
1440 14 100       29 ($self->{opt}->{noescape} ? $ref : $self->escape_value($ref)),
1441             '", $nl
1442             ));
1443             }
1444             else {
1445 2         7 return("$ref$nl");
1446             }
1447             }
1448              
1449              
1450             # Unfold hash to array if possible
1451              
1452 2169 100 100     16896 if(UNIVERSAL::isa($ref, 'HASH') # It is a hash
      66        
      100        
1453             and keys %$ref # and it's not empty
1454             and $self->{opt}->{keyattr} # and folding is enabled
1455             and !$is_root # and its not the root element
1456             ) {
1457 2003         2318 $ref = $self->hash_to_array($name, $ref);
1458             }
1459              
1460              
1461 2169         2012 my @result = ();
1462 2169         1270 my($key, $value);
1463              
1464              
1465             # Handle hashrefs
1466              
1467 2169 100       3382 if(UNIVERSAL::isa($ref, 'HASH')) {
    100          
1468              
1469             # Reintermediate grouped values if applicable
1470              
1471 1980 100       2607 if($self->{opt}->{grouptags}) {
1472 12         14 $ref = $self->copy_hash($ref);
1473 12         31 while(my($key, $val) = each %$ref) {
1474 18 100       38 if($self->{opt}->{grouptags}->{$key}) {
1475             $ref->{$key} = $self->new_hashref(
1476 5         8 $self->{opt}->{grouptags}->{$key} => $val
1477             );
1478             }
1479             }
1480             }
1481              
1482              
1483             # Scan for namespace declaration attributes
1484              
1485 1980         1417 my $nsdecls = '';
1486 1980         1162 my $default_ns_uri;
1487 1980 100       2281 if($self->{nsup}) {
1488 5         8 $ref = $self->copy_hash($ref);
1489 5         14 $self->{nsup}->push_context();
1490              
1491             # Look for default namespace declaration first
1492              
1493 5 100       33 if(exists($ref->{xmlns})) {
1494 2         7 $self->{nsup}->declare_prefix('', $ref->{xmlns});
1495 2         24 $nsdecls .= qq( xmlns="$ref->{xmlns}");
1496 2         3 delete($ref->{xmlns});
1497             }
1498 5         12 $default_ns_uri = $self->{nsup}->get_uri('');
1499              
1500              
1501             # Then check all the other keys
1502              
1503 5         27 foreach my $qname (keys(%$ref)) {
1504 9         16 my($uri, $lname) = $self->{nsup}->parse_jclark_notation($qname);
1505 9 100       64 if($uri) {
1506 8 100       13 if($uri eq $xmlns_ns) {
1507 1         3 $self->{nsup}->declare_prefix($lname, $ref->{$qname});
1508 1         15 $nsdecls .= qq( xmlns:$lname="$ref->{$qname}");
1509 1         2 delete($ref->{$qname});
1510             }
1511             }
1512             }
1513              
1514             # Translate any remaining Clarkian names
1515              
1516 5         8 foreach my $qname (keys(%$ref)) {
1517 8         12 my($uri, $lname) = $self->{nsup}->parse_jclark_notation($qname);
1518 8 100       44 if($uri) {
1519 7 100 100     20 if($default_ns_uri and $uri eq $default_ns_uri) {
1520 4         6 $ref->{$lname} = $ref->{$qname};
1521 4         5 delete($ref->{$qname});
1522             }
1523             else {
1524 3         6 my $prefix = $self->{nsup}->get_prefix($uri);
1525 3 100       31 unless($prefix) {
1526             # $self->{nsup}->declare_prefix(undef, $uri);
1527             # $prefix = $self->{nsup}->get_prefix($uri);
1528 1         2 $prefix = $self->{ns_prefix}++;
1529 1         3 $self->{nsup}->declare_prefix($prefix, $uri);
1530 1         14 $nsdecls .= qq( xmlns:$prefix="$uri");
1531             }
1532 3         6 $ref->{"$prefix:$lname"} = $ref->{$qname};
1533 3         4 delete($ref->{$qname});
1534             }
1535             }
1536             }
1537             }
1538              
1539              
1540 1980         1316 my @nested = ();
1541 1980         1220 my $text_content = undef;
1542 1980 100       2185 if($named) {
1543 1977         2565 push @result, $indent, '<', $name, $nsdecls;
1544             }
1545              
1546 1980 100       2206 if(keys %$ref) {
1547 1977         1289 my $first_arg = 1;
1548 1977         2293 foreach my $key ($self->sorted_keys($name, $ref)) {
1549 3948         3135 my $value = $ref->{$key};
1550 3948 100       5661 next if(substr($key, 0, 1) eq '-');
1551 3946 100       4550 if(!defined($value)) {
1552 5 100       9 next if $self->{opt}->{suppressempty};
1553 4 100 66     14 unless(exists($self->{opt}->{suppressempty})
1554             and !defined($self->{opt}->{suppressempty})
1555             ) {
1556 2 100       244 carp 'Use of uninitialized value' if warnings::enabled();
1557             }
1558 4 100       31 if($key eq $self->{opt}->{contentkey}) {
1559 1         2 $text_content = '';
1560             }
1561             else {
1562 3 100       6 $value = exists($self->{opt}->{suppressempty}) ? {} : '';
1563             }
1564             }
1565              
1566 3945 100 66     7596 if(!ref($value)
      66        
1567             and $self->{opt}->{valueattr}
1568             and $self->{opt}->{valueattr}->{$key}
1569             ) {
1570             $value = $self->new_hashref(
1571 2         5 $self->{opt}->{valueattr}->{$key} => $value
1572             );
1573             }
1574              
1575 3945 100 66     6422 if(ref($value) or $self->{opt}->{noattr}) {
1576 187         465 push @nested,
1577             $self->value_to_xml($value, $key, "$indent ");
1578             }
1579             else {
1580 3758 100       3718 if($key eq $self->{opt}->{contentkey}) {
1581 19 50       30 $value = $self->escape_value($value) unless($self->{opt}->{noescape});
1582 19         27 $text_content = $value;
1583             }
1584             else {
1585 3739 100       6105 $value = $self->escape_attr($value) unless($self->{opt}->{noescape});
1586             push @result, "\n$indent " . ' ' x length($name)
1587 3739 100 100     5759 if($self->{opt}->{attrindent} and !$first_arg);
1588 3739         4729 push @result, ' ', $key, '="', $value , '"';
1589 3739         3811 $first_arg = 0;
1590             }
1591             }
1592             }
1593             }
1594             else {
1595 3         3 $text_content = '';
1596             }
1597              
1598 1979 100 100     5413 if(@nested or defined($text_content)) {
1599 180 100       178 if($named) {
1600 177         158 push @result, ">";
1601 177 100       183 if(defined($text_content)) {
1602 22         16 push @result, $text_content;
1603 22 50       39 $nested[0] =~ s/^\s+// if(@nested);
1604             }
1605             else {
1606 155         141 push @result, $nl;
1607             }
1608 177 100       227 if(@nested) {
1609 155         199 push @result, @nested, $indent;
1610             }
1611 177         225 push @result, '", $nl;
1612             }
1613             else {
1614 3         3 push @result, @nested; # Special case if no root elements
1615             }
1616             }
1617             else {
1618 1799         1602 push @result, " />", $nl;
1619             }
1620 1979 100       2848 $self->{nsup}->pop_context() if($self->{nsup});
1621             }
1622              
1623              
1624             # Handle arrayrefs
1625              
1626             elsif(UNIVERSAL::isa($ref, 'ARRAY')) {
1627 188         207 foreach $value (@$ref) {
1628 2851 100 66     3757 next if !defined($value) and $self->{opt}->{suppressempty};
1629 2850 100       4949 if(!ref($value)) {
    100          
1630             push @result,
1631             $indent, '<', $name, '>',
1632 930 100       1453 ($self->{opt}->{noescape} ? $value : $self->escape_value($value)),
1633             '$nl";
1634             }
1635             elsif(UNIVERSAL::isa($value, 'HASH')) {
1636 1877         2204 push @result, $self->value_to_xml($value, $name, $indent);
1637             }
1638             else {
1639 43         104 push @result,
1640             $indent, '<', $name, ">$nl",
1641             $self->value_to_xml($value, 'anon', "$indent "),
1642             $indent, '$nl";
1643             }
1644             }
1645             }
1646              
1647             else {
1648 1         85 croak "Can't encode a value of type: " . ref($ref);
1649             }
1650              
1651              
1652 2167         2236 delete $self->{_ancestors}->{$refaddr};
1653              
1654 2167         7686 return(join('', @result));
1655             }
1656              
1657              
1658             ##############################################################################
1659             # Method: sorted_keys()
1660             #
1661             # Returns the keys of the referenced hash sorted into alphabetical order, but
1662             # with the 'key' key (as in KeyAttr) first, if there is one.
1663             #
1664              
1665             sub sorted_keys {
1666 1977     1977 1 1649 my($self, $name, $ref) = @_;
1667              
1668 1977 50       2682 return keys %$ref if $self->{opt}->{nosort};
1669              
1670 1977         3557 my %hash = %$ref;
1671 1977         1797 my $keyattr = $self->{opt}->{keyattr};
1672              
1673 1977         1198 my @key;
1674              
1675 1977 100       2499 if(ref $keyattr eq 'HASH') {
    100          
1676 1877 100 100     5843 if(exists $keyattr->{$name} and exists $hash{$keyattr->{$name}->[0]}) {
1677 1847         1768 push @key, $keyattr->{$name}->[0];
1678 1847         1938 delete $hash{$keyattr->{$name}->[0]};
1679             }
1680             }
1681             elsif(ref $keyattr eq 'ARRAY') {
1682 95         70 foreach (@{$keyattr}) {
  95         114  
1683 237 100       326 if(exists $hash{$_}) {
1684 21         22 push @key, $_;
1685 21         22 delete $hash{$_};
1686 21         23 last;
1687             }
1688             }
1689             }
1690              
1691 1977         4430 return(@key, sort keys %hash);
1692             }
1693              
1694             ##############################################################################
1695             # Method: escape_value()
1696             #
1697             # Helper routine for automatically escaping values for XMLout().
1698             # Expects a scalar data value. Returns escaped version.
1699             #
1700              
1701             sub escape_value {
1702 4697     4697 1 3989 my($self, $data) = @_;
1703              
1704 4697 100       5719 return '' unless(defined($data));
1705              
1706 4695         4451 $data =~ s/&/&/sg;
1707 4695         3364 $data =~ s/
1708 4695         3322 $data =~ s/>/>/sg;
1709 4695         3204 $data =~ s/"/"/sg;
1710              
1711 4695 100       10083 my $level = $self->{opt}->{numericescape} or return $data;
1712              
1713 4         9 return $self->numeric_escape($data, $level);
1714             }
1715              
1716             sub numeric_escape {
1717 4     4 1 7 my($self, $data, $level) = @_;
1718              
1719 4 100       10 if($self->{opt}->{numericescape} eq '2') {
1720 2         17 $data =~ s/([^\x00-\x7F])/'&#' . ord($1) . ';'/gse;
  2         10  
1721             }
1722             else {
1723 2         7 $data =~ s/([^\x00-\xFF])/'&#' . ord($1) . ';'/gse;
  1         4  
1724             }
1725              
1726 4         12 return $data;
1727             }
1728              
1729             ##############################################################################
1730             # Method: escape_attr()
1731             #
1732             # Helper routine for escaping attribute values. Defaults to escape_value(),
1733             # but may be overridden by a subclass to customise behaviour.
1734             #
1735              
1736             sub escape_attr {
1737 3737     3737 1 2463 my $self = shift;
1738              
1739 3737         3884 return $self->escape_value(@_);
1740             }
1741              
1742              
1743             ##############################################################################
1744             # Method: hash_to_array()
1745             #
1746             # Helper routine for value_to_xml().
1747             # Attempts to 'unfold' a hash of hashes into an array of hashes. Returns a
1748             # reference to the array on success or the original hash if unfolding is
1749             # not possible.
1750             #
1751              
1752             sub hash_to_array {
1753 2003     2003 0 1473 my $self = shift;
1754 2003         1430 my $parent = shift;
1755 2003         1255 my $hashref = shift;
1756              
1757 2003         1708 my $arrayref = [];
1758              
1759 2003         1473 my($key, $value);
1760              
1761 2003 50       5804 my @keys = $self->{opt}->{nosort} ? keys %$hashref : sort keys %$hashref;
1762 2003         2232 foreach $key (@keys) {
1763 3844         2948 $value = $hashref->{$key};
1764 3844 100       9343 return($hashref) unless(UNIVERSAL::isa($value, 'HASH'));
1765              
1766 1948 100       2272 if(ref($self->{opt}->{keyattr}) eq 'HASH') {
1767 1931 100       2370 return($hashref) unless(defined($self->{opt}->{keyattr}->{$parent}));
1768             push @$arrayref, $self->copy_hash(
1769 1929         2199 $value, $self->{opt}->{keyattr}->{$parent}->[0] => $key
1770             );
1771             }
1772             else {
1773 17         50 push(@$arrayref, { $self->{opt}->{keyattr}->[0] => $key, %$value });
1774             }
1775             }
1776              
1777 105         189 return($arrayref);
1778             }
1779              
1780              
1781             ##############################################################################
1782             # Method: copy_hash()
1783             #
1784             # Helper routine for hash_to_array(). When unfolding a hash of hashes into
1785             # an array of hashes, we need to copy the key from the outer hash into the
1786             # inner hash. This routine makes a copy of the original hash so we don't
1787             # destroy the original data structure. You might wish to override this
1788             # method if you're using tied hashes and don't want them to get untied.
1789             #
1790              
1791             sub copy_hash {
1792 1946     1946 1 2454 my($self, $orig, @extra) = @_;
1793              
1794 1946         5709 return { @extra, %$orig };
1795             }
1796              
1797             ##############################################################################
1798             # Methods required for building trees from SAX events
1799             ##############################################################################
1800              
1801             sub start_document {
1802 161     161 0 19479 my $self = shift;
1803              
1804 161 100       345 $self->handle_options('in') unless($self->{opt});
1805              
1806 161         193 $self->{lists} = [];
1807 161         368 $self->{curlist} = $self->{tree} = [];
1808             }
1809              
1810              
1811             sub start_element {
1812 3531     3531 0 1306640 my $self = shift;
1813 3531         3135 my $element = shift;
1814              
1815 3531         3352 my $name = $element->{Name};
1816 3531 100       6384 if($self->{opt}->{nsexpand}) {
1817 11   50     20 $name = $element->{LocalName} || '';
1818 11 100       16 if($element->{NamespaceURI}) {
1819 6         12 $name = '{' . $element->{NamespaceURI} . '}' . $name;
1820             }
1821             }
1822 3531         3107 my $attributes = {};
1823 3531 50       5575 if($element->{Attributes}) { # Might be undef
1824 3531         2353 foreach my $attr (values %{$element->{Attributes}}) {
  3531         6057  
1825 4144 100       4678 if($self->{opt}->{nsexpand}) {
1826 6   50     11 my $name = $attr->{LocalName} || '';
1827 6 100       8 if($attr->{NamespaceURI}) {
1828 4         8 $name = '{' . $attr->{NamespaceURI} . '}' . $name
1829             }
1830 6 50       7 $name = 'xmlns' if($name eq $bad_def_ns_jcn);
1831 6         12 $attributes->{$name} = $attr->{Value};
1832             }
1833             else {
1834 4138         6787 $attributes->{$attr->{Name}} = $attr->{Value};
1835             }
1836             }
1837             }
1838 3531         4030 my $newlist = [ $attributes ];
1839 3531         2353 push @{ $self->{lists} }, $self->{curlist};
  3531         3825  
1840 3531         2228 push @{ $self->{curlist} }, $name => $newlist;
  3531         4356  
1841 3531         5831 $self->{curlist} = $newlist;
1842             }
1843              
1844              
1845             sub characters {
1846 4943     4943 0 181848 my $self = shift;
1847 4943         3386 my $chars = shift;
1848              
1849 4943         4457 my $text = $chars->{Data};
1850 4943         3377 my $clist = $self->{curlist};
1851 4943         4374 my $pos = $#$clist;
1852              
1853 4943 100 100     15775 if ($pos > 0 and $clist->[$pos - 1] eq '0') {
1854 11         27 $clist->[$pos] .= $text;
1855             }
1856             else {
1857 4932         10315 push @$clist, 0 => $text;
1858             }
1859             }
1860              
1861              
1862             sub end_element {
1863 3531     3531 0 154777 my $self = shift;
1864              
1865 3531         2749 $self->{curlist} = pop @{ $self->{lists} };
  3531         5822  
1866             }
1867              
1868              
1869             sub end_document {
1870 161     161 0 9458 my $self = shift;
1871              
1872 161         197 delete($self->{curlist});
1873 161         182 delete($self->{lists});
1874              
1875 161         144 my $tree = $self->{tree};
1876 161         116 delete($self->{tree});
1877              
1878              
1879             # Return tree as-is to XMLin()
1880              
1881 161 100       1325 return($tree) if($self->{nocollapse});
1882              
1883              
1884             # Or collapse it before returning it to SAX parser class
1885              
1886 7 100       11 if($self->{opt}->{keeproot}) {
1887 1         2 $tree = $self->collapse({}, @$tree);
1888             }
1889             else {
1890 6         5 $tree = $self->collapse(@{$tree->[1]});
  6         12  
1891             }
1892              
1893 7 100       33 if($self->{opt}->{datahandler}) {
1894 2         5 return($self->{opt}->{datahandler}->($self, $tree));
1895             }
1896              
1897 5         92 return($tree);
1898             }
1899              
1900             *xml_in = \&XMLin;
1901             *xml_out = \&XMLout;
1902              
1903             1;
1904              
1905             __END__