Beefy Boxes and Bandwidth Generously Provided by pair Networks DiBona
XP is just a number
 
PerlMonks  

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"; }

ONE ERROR:

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

TWO ERRORS:

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

Thanks in advance

Cheers

Nick

Comment on XML Array/Hash Issue
Select or Download Code
Re: XML Array/Hash Issue
by toolic (Chancellor) 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 hdb (Parson) 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 Preceptor (Chaplain) 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 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.

    Jenda
    Enoch was right!
    Enjoy the last years of Rome.

Re: XML Array/Hash Issue
by Discipulus (Deacon) 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
    hth
    L*
    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.
Re: XML Array/Hash Issue
by choroba (Abbot) on Nov 21, 2013 at 10:21 UTC
    Using XML::XSH2, a wrapper around XML::LibXML:
    open file.xml ; for /errors/error echo (desc) ;
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1063583]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (15)
As of 2014-04-23 17:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (551 votes), past polls