carterniall has asked for the wisdom of the Perl Monks concerning the following question:

Hiya I am a newbie to PERL and I am trying to parse out an element from an XML document. I can successfully parse out the top level element (name) but the moment I try to parse out anything in the looping section it states that it is NOT AN ARRAY REFERENCE. The XML code is:
<?xml version='1.0' encoding='UTF-8'?> <Document> <open>0</open> <name>Gazetteer for Scotland: Settlements</name> <Placemark> <name><![CDATA[ Abbey Strand ]]></name> <description><![CDATA[ The Abbey Strand is a short street, lying immediately outside the +Palace of Holyroodhouse, which represents the very last section of Ed +inburgh's Royal Mile. It represented the extent of the precincts of H +olyrood Abbey (the ruins of which stand next to the palace) and hence + the boundary of 'sanctuary', which is still marked by brass studs an +d the letter 'S' in the road. <p><a href="http://getamap.ordnancesurvey.co.uk/getamap/frames.htm?map +Action=zoomabs&mapX=326775&mapY=673975&zoomLevel=6&isGeo=y">SHOW OS M +AP</a>, ]]></description> <LookAt> <longitude>-3.17423</longitude> <latitude>55.95277</latitude> <range>2000</range> <tilt>75</tilt> <heading>0</heading> </LookAt> <Point> <coordinates>-3.17423,55.95277,0</coordinates> </Point> </Placemark> <Placemark> <name><![CDATA[ Abbeyhill ]]></name> <description><![CDATA[ A small district of Edinburgh, is centred to the south of London R +oad, a half-mile (1 km) east of Princes Street, Abbeyhill lies on a r +idge that runs east from Calton Hill to Meadowbank. The district take +s its name from Holyrood Abbey, indeed there is also a road called Ab +beyhill leading from the Abbey which lies a ruin next to the Palace o +f Holyroodhouse. <p><a href="http://getamap.ordnancesurvey.co.uk/geta +map/frames.htm?mapAction=zoomabs&mapX=327000&mapY=674400&zoomLevel=6& +isGeo=y">SHOW OS MAP</a>, ]]></description> <LookAt> <longitude>-3.17075</longitude> <latitude>55.95705</latitude> <range>2000</range> <tilt>75</tilt> <heading>0</heading> </LookAt> <Point> <coordinates>-3.17075,55.95705,0</coordinates> </Point> </Placemark> <Placemark> <name><![CDATA[ Abbeymount ]]></name> <description><![CDATA[ From back of Place Names of Edinburgh Book (can identify district +by streets it references!) <p><a href="http://getamap.ordnancesurvey.co.uk/getamap/frames.htm?map +Action=zoomabs&mapX=326900&mapY=674200&zoomLevel=6&isGeo=y">SHOW OS M +AP</a>, ]]></description> <LookAt> <longitude>-3.1723</longitude> <latitude>55.95524</latitude> <range>2000</range> <tilt>75</tilt> <heading>0</heading> </LookAt> <Point> <coordinates>-3.1723,55.95524,0</coordinates> </Point> </Placemark> </Document>
I am aware that this is an undefined KML as ultimatly I want to parse the KML but am keeping it simple for the moment. The PERL script I am using is:
#!/usr/bin/perl # Script to illustrate how to parse a simple XML file # and dump its contents in a Perl hash record. use XML::Simple; use XML::Parser; use LWP::Simple; use Data::Dumper; my $url= "http://xweb.geos.ed.ac.uk/~s0341330/module3/test.xml"; my $xml = get ($url) or die "I can't get the feed you want"; my $parser = XML::Simple->new( ); my $Document = $parser->XMLin("$xml"); foreach my $Placemark (@{$Document->{Placemark}}) { my $var = $Placemark->{name} . "\n"; print "$var"; }
I think it is because the above gives a hashref (?) instead of an array but I have no idea how then to parse out what I want! Please help! Niall

Replies are listed 'Best First'.
Re: XML::Simple troubles
by moritz (Cardinal) on May 23, 2008 at 12:09 UTC
    Try this one:
    #!/usr/bin/perl -w use strict; use warnings; use XML::Simple; use Data::Dumper; my $Document =XMLin("foo.xml"); while (my ($key, $val) = each %{$Document->{Placemark}}){ print "Found key '$key' with value " . Dumper($val); }

    (I stored the XML file locally on disc, obviously).

      Thanks for the reply but the suggestion doesn't seem to work. When running it in UNIX I get the following response:
      Pseudo-hashes are deprecated at pmonks.pl line 9. Pseudo-hashes are deprecated at pmonks.pl line 9. Found key 'LookAt' with value $VAR1 = undef; Pseudo-hashes are deprecated at pmonks.pl line 10. Pseudo-hashes are deprecated at pmonks.pl line 10. Argument "#SGStyle" isn't numeric in each at pmonks.pl line 10. Bad index while coercing array into hash at pmonks.pl line 10.
      Am I correct in saying that % denotes a hash as opposed to @ denoting an array? Also would the code suggested return all child nodes of the placemark element? What I really want to do is return out the
      <Point> <coordinates>-3,55</coordinates> </Point>
      so that I can run them in another SQL query. Surely to do this I would have to identify the lement I desire e.g. Placemark->Point->coordinates?? I appreciate your help on this one, I am just a little unsure as to the significance of Key and Value Cheers, Niall
        Are you sure you ran exactly the same piece of code that I posted? It works for me both with perl 5.8.8 and perl 5.10.0. Which perl version did you use?
        Am I correct in saying that % denotes a hash as opposed to @ denoting an array?

        Yes. See perldsc, perlreftut, perlref and perldata for details.

        Maybe you want something along these lines:

        #!/usr/bin/perl use strict; use warnings; use XML::Simple; use Data::Dumper; my $Document =XMLin("foo.xml"); while (my ($key, $val) = each %{$Document->{Placemark}}){ printf "%s is at %s\n", $key, $val->{Point}{coordinates}; } __END__ Abbeyhill is at -3.17075,55.95705,0 Abbey Strand is at -3.17423,55.95277,0 Abbeymount is at -3.1723,55.95524,0