in reply to XML parsing

I worked through your XML example (which was malformed... I hope you made mistakes while re-typing, or else you really need to fix the source XML file). Your problem seems to be that XML::Simple returns different types of data depending on what's in the XML file. If it finds only one element, it puts a scalar in the returned hash. If it finds more than one, it returns a reference to an array of data.

Not having used this module myself, I thought this was difficult behavior, but after RTFM, it turns out there is an option (clearly marked "important") to force certain elements to always be represented as arrays, even if there is only one. I turned that on and then got the code to run on a modified version of your XML block. I tried to mark the important parts in the code below:
#!/usr/bin/perl # use module use strict; use warnings; use XML::Simple; use Data::Dumper; # create object my $xml = new XML::Simple (KeyAttr=>[], ForceArray => ['function']); # IMPORTANT ^^^^^^^^^^ # read XML file my $data = $xml->XMLin("hosts.xml"); my $e = $data->{'host'}; print "Name: ", $e->{name}, "\n"; # IMPORTANT: Use a loop to process all the possible # functions, instead of just one. foreach my $fct ( @{$e->{'function'}} ){ print "Function: ", $fct, "\n"; }
<allHosts> <host name="jimmy"> <function>web</function> <function>dns</function> <location>miami</location> </host> </allHosts>
Please use strict and warnings int he future, as it would have alerted you to the problems in your code instead of silently giving you no output.

Replies are listed 'Best First'.
Re^2: XML parsing
by Anonymous Monk on May 09, 2005 at 23:29 UTC
    Using your code, I get the following error

    Pseudo-hashes are deprecated at ./test.pl line 19.
      Please don't just "use my code". Your XML file is different from the block I used, in that I only have one host and you have several.

      The key point (I'm sorry if it wasn't clear) I was making was that XML::Simple returns a reference to an array when there is more than one element with the same name. You need to either differentiate between the "singular" and the "plural" using ref, or force the element to be an array reference all the time using ForceArray => 1 in your options.

      The structure and form of the data XML::Simple returns depends on the XML it parses. I think that's the crux of your problem.