File Coverage

blib/lib/XML/Simple.pm
Criterion Covered Total %
statement 651 683 95.3
branch 407 454 89.6
condition 97 126 76.9
subroutine 47 48 97.9
pod 14 39 35.9
total 1216 1350 90.0


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