Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

XML Array/Hash Issue

by nickt9999 (Acolyte)
on Nov 20, 2013 at 19:36 UTC ( #1063583=perlquestion: print w/replies, xml ) Need Help??
nickt9999 has asked for the wisdom of the Perl Monks concerning the following question:

Hi All

I am a newbie and require some help

I am parsing an XML file for errors, the format is as follows

<errors> <error> <desc></desc> </error> </errors>

I would like to be able to print the description of the error, the problem I have is that when there is only one error my script bombs out with a Not an ARRAY reference. It works perfectly fine when there is two errors in the XML file

my current code is:

my $errorArray = $data->{errors}; foreach my $error ( @{ $errorArray->{error} } ) { print NEW "$error->{desc}\n"; }


HASH(0x7fb3d8973fa8) $VAR1 = { 'desc' => 'Slave not running' };


ARRAY(0x7ffc84006ad0) $VAR1 = [ { 'desc' => 'Slave not running' }, { 'desc' => 'TEST123' } ];

Thanks in advance



Replies are listed 'Best First'.
Re: XML Array/Hash Issue
by hdb (Monsignor) on Nov 20, 2013 at 20:19 UTC

    Should you be using XML::Simple, then check the documentation for the ForceArray attribute. It will enforce that even single elements will be stored as array references.

      Many thanks, that's exactly what I needed
Re: XML Array/Hash Issue
by toolic (Bishop) on Nov 20, 2013 at 19:46 UTC
    How are you parsing your XML? With XML::Simple? ForceArray, or something like it?
      Many thanks, thats exactly what I needed. I was trying to do it in code.
Re: XML Array/Hash Issue
by Preceptor (Deacon) on Nov 20, 2013 at 21:37 UTC

    Your problem is that you're getting a scalar in one mode, and an array in the other - and so your coercion is failing.

    I would take a slightly different approach, and use XML::Twig, which is my current favorite XML parser.

    use strict; use warnings; use XML::Twig; my $XML = "<errors> <error> <desc>First Error</desc> </error> <error> <desc>Second Error</desc> </error> </errors>"; sub print_error { my ( $twig, $error ) = @_; print "NEW: ",$error -> first_child_text('desc'),"\n"; } my $parser = XML::Twig -> new ( 'twig_handlers' => { 'error' => \&prin +t_error } ); $parser -> parse ( $XML );

    You could also find the 'children' method within XML::Twig to be handy if you wanted to do it a different way.

    sub process_all_errors { my ( $twig, $errors_list ) = @_; foreach my $error ( $errors_list -> children ( "error" ) ) { print "NEW: ",$error -> first_child_text('desc'),"\n"; } } my $other_parser = XML::Twig -> new ( 'twig_handlers' => { 'errors' => + \&process_all_errors } ); $other_parser -> parse ( $XML );

    The former invokes the subroutine each time the parser hits an 'errors' element. (So twice). The latter invokes the sub just once (for each 'error') but then cycles through the 'errors' within it. (Which is optimal depends on what you're trying to do exactly, which is why I've given both examples).

Re: XML Array/Hash Issue
by choroba (Bishop) on Nov 21, 2013 at 10:21 UTC
    Using XML::XSH2, a wrapper around XML::LibXML:
    open file.xml ; for /errors/error echo (desc) ;
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: XML Array/Hash Issue
by Jenda (Abbot) on Nov 21, 2013 at 09:55 UTC

    See Simpler than XML::Simple. Replacing XML::Simple by a well set XML::Rules will require minimal changes to the script(s) while ensuring a consistent data structure.

    Enoch was right!
    Enjoy the last years of Rome.

Re: XML Array/Hash Issue
by Discipulus (Monsignor) on Nov 21, 2013 at 10:16 UTC
    Oh yes, as stated by Preceptor XML::Twig is my choice too.
    It tempt you to resolve such simple problems in a oneliner:
    perl -e "use XML::Twig; $t= XML::Twig->new( pretty_print => 'indented' +,twig_handlers => {'/errors/error/desc'=>sub{print $_[1]->text,qq(\n +);},});$t->parsefile($ARGV[0]);" error.xml
    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1063583]
Front-paged by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (5)
As of 2018-06-25 10:16 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (126 votes). Check out past polls.