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

Howdy Monks

I am having a bit of a doozy problem with parsing out values of a KML.
I have managed to get the KML into a hash and print off the values I desire although the hash is breaking my KML structure apart.

The trouble is that each attribute is being placed as a seperate hash within the node.
This will present problems when I am trying to take my value, use it to return another value and place this value back into the KML at the correct place which is what I need.

I am currently using XML::Simple and suspect that this does not recognise attributes as attributes and I am struggling to comprehend if there are better parsers which will maintain my KML/XML structure?

Another problem which I seem to be having with XML::Simple is that the <name> element of the KML is not being preserved, the value is instead being used as the Hash key value and not preserving the value as the value of the <name> element! Again, is this an XML:Simple perculiarity and is it a known problem of XML parsers?

Any suggestions/explanations would be very useful,
Many thanks
Niall Carter

Replies are listed 'Best First'.
Re: Using KML in XML::Simple
by Fletch (Bishop) on May 27, 2008 at 17:44 UTC

    Well judging by the sample code and sample XML you've helpfully provided it's easy to see where the problem is . . .

    Oh, never mind. At any rate, a quick perusal of the XML::Simple docs show that it certainly does handle attributes and shows the format the returned data takes. So that's probably the wrong tree up which to be barking.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: Using KML in XML::Simple
by grantm (Parson) on May 28, 2008 at 02:20 UTC

    If you're going to use XML::Simple, then please take a few minutes to read this node which shows ways to avoid common pitfalls (such as not specifying KeyAttr which is causing your 'name' problem; and not specifying ForceArray which is probably causing your other problem).

    Once you've read that, I'd really recommend using XML::LibXML instead - it will be easier. This node discusses moving from XML::Simple to XML::LibXML.

      Thanks monks.

      I thought is best to start simple and build up.
      So firstly, before getting onto attributes and order let's just try to get the parser loading in KML!

      I am using this <kml> (thanks Fletch):

      <?xml version='1.0' encoding='UTF-8'?><kml xmlns='http://earth.google. +com/kml/2.0'> <Document> <open>0</open> <name>Gazetteer for Scotland: Settlements</name> <Placemark> <name><![CDATA[ Hermits and Termits ]]></name> <!-- <Snippet> </Snippet> --> <styleUrl>#SGStyle</styleUrl> <description><![CDATA[A small harled five-bay mansion lying gable- +on to St Leonard's Street in S Central Edinburgh, Hermits and Termits + was built in 1734 for William Clifton, a Solicitor of Excise. It too +k its name from the poetic-slang for a pair of crofts, <i>Hermitis</i +> and <i>Terraris</i>, which can be traced back to at least the 15th +century and were associated with the St Leonard's Almshouses. Hermits and Termits was restored in 1982, an early project by local ar +chitect Ben Tindall, to form his own residence. The interior is panel +led and the staircase features a fine mahogany balustrade. <p><a href="http://getamap.ordnancesurvey.co.uk/getamap/frames.htm?map +Action=zoomabs&mapX=326472&mapY=672772&zoomLevel=6&isGeo=y">SHOW OS M +AP</a>,</p> <p><a href="http://www.geo.ed.ac.uk/scotgaz/ features/featurefirst16994.html"//]]></description> <LookAt> <longitude>-3.17876</longitude> <latitude>55.94218</latitude> <range>2000</range> <tilt>75</tilt> <heading>0</heading> </LookAt> <Point id="g16994"> <coordinates>-3.17876,55.94218,0</coordinates> </Point> <extra xmlns:gml="http://www.opengeospatial.org/standards/gml"> <Point id="g16994" srsName="EPSG27700"> <pos>326472,672772</pos> </Point> <typea>House, Mansion or Palace</typea> <typeb>Historic Building</typeb> <typec></typec> </extra> <Link>http://www.geo.ed.ac.uk/scotgaz/features/featurefirst16994.h +tml </Link> </Placemark> <Placemark> <name><![CDATA[ Queen's Drive ]]></name> <!-- <Snippet> </Snippet> --> <styleUrl>#SGStyle</styleUrl> <description><![CDATA[A road which largely encircles the hills wit +hin Edinburgh's Holyrood Park, the Queen's Drive is known as one of t +he finest carriage drives in Europe. From its lowest point to the eas +t of Palace of Holyroodhouse, the road rises sharply onto the eastern + and southern flanks of Arthur's Seat (251m / 823 feet). The higher p +ortions give spectacular views over the city. <p><a href="http://getamap.ordnancesurvey.co.uk/getamap/frames.htm?map +Action=zoomabs&mapX=326643&mapY=672943&zoomLevel=6&isGeo=y">SHOW OS M +AP</a>,</p> <p><a href="http://www.geo.ed.ac.uk/scotgaz/ features/featurefirst8976.html"//]]></description> <LookAt> <longitude>-3.17606</longitude> <latitude>55.94367</latitude> <range>2000</range> <tilt>75</tilt> <heading>0</heading> </LookAt> <Point id="g8976"> <coordinates>-3.17606,55.94367,0</coordinates> </Point> <extra xmlns:gml="http://www.opengeospatial.org/standards/gml"> <Point id="g8976" srsName="EPSG27700"> <pos>326643,672943</pos> </Point> <typea>Road or Street</typea> <typeb></typeb> <typec></typec> </extra> <Link>http://www.geo.ed.ac.uk/scotgaz/features/featurefirst8976.ht +ml </Link> </Placemark> <Placemark> <name><![CDATA[ Queen's Hall, The ]]></name> <!-- <Snippet> </Snippet> --> <styleUrl>#SGStyle</styleUrl> <description><![CDATA[Located on the west side of Clerk Street, in + the Newington District of Edinburgh, the Queen's Hall represents the + principal venue on the south-side of the city for concerts. Built in + 1823 as the Hope Park Chapel of Ease, the building has a two-storey +villa frontage, with a tall and slender classical steeple. Latterly t +he Newington and St. Leonard's Church, it was converted into a concer +t hall in 1979, and opened by Her Majesty Queen Elizabeth II, the 850 +-seat auditorium still strongly reflects its ecclesiastical origins, +although the pulpit has been replaced by an early 19th Century chambe +r organ. Painted 18th Century panels displaying the Commandments and +the Lord's Prayer, which were brought from the former Buccleuch Paris +h Church in 1950, can be seen on the stairs. Noted particularly for its baroque and classical music concerts, the H +all is home to the world-class Scottish Chamber Orchestra, but also o +ffers a programme of jazz, folk and contemporary music, in addition t +o theatre, comedy and opera as well as acting as an important venue f +or the Edinburgh International Festival. <p><a href="http://getamap.ordnancesurvey.co.uk/getamap/frames.htm?map +Action=zoomabs&mapX=326298&mapY=672698&zoomLevel=6&isGeo=y">SHOW OS M +AP</a>,</p> <p><a href="http://www.geo.ed.ac.uk/scotgaz/ features/featurefirst7848.html"//]]></description> <LookAt> <longitude>-3.18151</longitude> <latitude>55.94126</latitude> <range>2000</range> <tilt>75</tilt> <heading>0</heading> </LookAt> <Point id="g7848"> <coordinates>-3.18151,55.94126,0</coordinates> </Point> <extra xmlns:gml="http://www.opengeospatial.org/standards/gml"> <Point id="g7848" srsName="EPSG27700"> <pos>326298,672698</pos> </Point> <typea>Entertainment Venue</typea> <typeb>Historic Building</typeb> <typec></typec> </extra> <Link>http://www.geo.ed.ac.uk/scotgaz/features/featurefirst7848.ht +ml </Link> </Placemark> <Placemark> <name><![CDATA[ St Leonard's ]]></name> <!-- <Snippet> Saint Leonard's </Snippet> --> <styleUrl>#SGStyle</styleUrl> <description><![CDATA[A small district of S Central Edinburgh, St +Leonard's lies a mile (1.5 km) south southeast of the city centre. Th +e area represented land granted to Holyrood Abbey by King David I (c. +1080 - 1153), and while once being much larger, today is constrained +between Holyrood Park Road in the south and Dumbiedykes and the Pleas +ance in the north. Once associated with brewing, St. Leonard's Statio +n was also the terminus of the Innocent Railway. St Leonard's School +(1879) is now converted into private flats. The Police Headquarters f +or Central Edinburgh ('A' Division) is located in the modern St. Leon +ard's Police Station. <p><a href="http://getamap.ordnancesurvey.co.uk/getamap/frames.htm?map +Action=zoomabs&mapX=326400&mapY=672800&zoomLevel=6&isGeo=y">SHOW OS M +AP</a>,</p> <p><a href="http://www.geo.ed.ac.uk/scotgaz/ features/featurefirst7865.html"//]]></description> <LookAt> <longitude>-3.17992</longitude> <latitude>55.94259</latitude> <range>2000</range> <tilt>75</tilt> <heading>0</heading> </LookAt> <Point id="g7865"> <coordinates>-3.17992,55.94259,0</coordinates> </Point> <extra xmlns:gml="http://www.opengeospatial.org/standards/gml"> <Point id="g7865" srsName="EPSG27700"> <pos>326400,672800</pos> </Point> <typea>Urban District</typea> <typeb></typeb> <typec></typec> </extra> <Link>http://www.geo.ed.ac.uk/scotgaz/features/featurefirst7865.ht +ml </Link> </Placemark> <ExtendedData xmlns:GforS="http://www.geo.ed.ac.uk/scotgaz/"> <GforS:Copyright> <![CDATA[ <p>All Images and Text are Copyright (c) The Gazette +er for Scotland 1995-2008 </p>]]> </GforS:Copyright> </ExtendedData> </Document> </kml>
      which has been generated from a perl script here:.

      The script I am using to parse the KML is:

      #!/usr/bin/perl use strict; use warnings; use XML::Simple; use Data::Dumper; use LWP::Simple; use XML::Parser; my $url= "http://www.geo.ed.ac.uk/scotgaz/cgi_bin/mid/cygnus/scotgaz1. +5.pl"; my $foo = get ($url) or die "I can't get the feed you want"; my $xml = XML::Simple->new( ); my $parse =$xml->XMLin($foo); while (my ($key, $val) = each %{$parse->{Placemark}}) { printf "%s is at %s\n", $key, $val->{Point}{coordinates}; }
      This script works when I remove the <kml> tages from the <kml> and so I think that it is due to something with XML::Simple where the first ankle brackets are removed automatically. When I run the script in debug mode the $foo contains the URL and the $parse contains the corect hash.
      The value I ask is not brought back though and I am failing to see why! After this works I will then go onto the look at forceArray (which I have had some success with in the past and the other XML::Simple problems....... one small step at a time though!

      Many thanks for the helpful explanations
      niall

        The value I ask is not brought back though and I am failing to see why! After this works I will then go onto the look at forceArray (which I have had some success with in the past and the other XML::Simple problems.......

        That you don't get the multiple values back for Placemark is immediately related to you not using ForceArray. So you need to attack the "two problems" in one go.

        A Perl hash can only store one value for a single key. You have multiple Placemark tags, so these cannot be stored in a single hash entry except as an array (reference). Hence, you will need (untested):

        my @places = @{$parse->{Placemark}}; while (my ($key, $val) = each %{$place}) { printf "%s is at %s\n", $key, $val->{Point}{coordinates}; }

        That code won't work for a file with only a single Placemark entry, hence you will need ForceArray.

        See References Quick Reference.

Re: Using KML in XML::Simple
by psini (Deacon) on May 27, 2008 at 17:59 UTC

    I myself don't use XML::Simple because, as every "simple" implementation, is a hell to use in not-so-simple cases...

    I suggest you see XMS::SAX that is a full XML parser and provides, via XML::Class::Factory the means to create your handlers to the parser events.

    As a serializer I am completely satisfied using XML::Writer which is simple and pratical for my needs; I suppose there are other XML serializer in CPAN, but I don't know them

    Update If you want to use XML::Simple, try adding ForceArray => 1, KeyAttr=>[] to the options passed to the constructor.

    Rule One: Do not act incautiously when confronting a little bald wrinkly smiling man.

Re: Using KML in XML::Simple
by moritz (Cardinal) on May 28, 2008 at 08:48 UTC
      Monks Apologies moritz.
      So I have had a look at the XML::Simple troubles and am now using forcearray so that when debugging and printing the contents of the $parse I have this returned:
      0 HASH(0x65deac0) 'Document' => HASH(0x65df390) 'ExtendedData' => HASH(0x661ddb0) 'GforS:Copyright' => "\cJ\cI\cI <p>All Images and Text are Co +pyright (c) The Gazetteer for Scotland 1995-2008 </p>\cJ\cI " 'xmlns:GforS' => 'http://www.geo.ed.ac.uk/scotgaz/' 'Placemark' => ARRAY(0x65e30f0) 0 HASH(0x65fdda0) 'Link' => 'http://www.geo.ed.ac.uk/scotgaz/features/featur +efirst16994.html ' 'LookAt' => HASH(0x660fc30) 'heading' => 0 'latitude' => 55.94218 'longitude' => '-3.17876' 'range' => 2000 'tilt' => 75 'Point' => HASH(0x66195c0) 'coordinates' => '-3.17876,55.94218,0' 'id' => 'g16994' 'description' => "A small harled five-bay mansion lying ga +ble-on to St Leonard's Street in S Central Edinburgh, Hermits and Ter +mits was built in 1734 for William Clifton, a Solicitor of Excise. It + took its name from the poetic-slang for a pair of crofts, <i>Hermiti +s</i> and <i>Terraris</i>, which can be traced back to at least the 1 +5th century and were associated with the St Leonard's Almshouses.\cJ\ +cJHermits and Termits was restored in 1982, an early project by local + architect Ben Tindall, to form his own residence. The interior is pa +nelled and the staircase features a fine mahogany balustrade.\cJ<p><a + href=\"http://getamap.ordnancesurvey.co.uk/getamap/frames.htm?mapAct +ion=zoomabs&mapX=326472&mapY=672772&zoomLevel=6&isGeo=y\">SHOW OS MAP +</a>,</p>\cJ <p><a href=\"http://www.geo.ed.ac.uk/scotgaz/\cJ \ +cI\cIfeatures/featurefirst16994.html\"//" 'extra' => HASH(0x6627c30) 'Point' => HASH(0x6627f00) 'id' => 'g16994' 'pos' => '326472,672772' 'srsName' => 'EPSG27700' 'typea' => 'House, Mansion or Palace' 'typeb' => 'Historic Building' 'typec' => HASH(0x6606ae0) empty hash 'xmlns:gml' => 'http://www.opengeospatial.org/standards +/gml' 'name' => ARRAY(0x66021f0) 0 ' Hermits and Termits ' 'styleUrl' => '#SGStyle' 1 HASH(0x660f7f0) 'Link' => 'http://www.geo.ed.ac.uk/scotgaz/features/featur +efirst8976.html ' 'LookAt' => HASH(0x6606ce0) 'heading' => 0 'latitude' => 55.94367 'longitude' => '-3.17606' 'range' => 2000 'tilt' => 75 'Point' => HASH(0x6606bd0) 'coordinates' => '-3.17606,55.94367,0' 'id' => 'g8976' 'description' => "A road which largely encircles the hills + within Edinburgh's Holyrood Park, the Queen's Drive is known as one +of the finest carriage drives in Europe. From its lowest point to the + east of Palace of Holyroodhouse, the road rises sharply onto the eas +tern and southern flanks of Arthur's Seat (251m / 823 feet). The high +er portions give spectacular views over the city.\cJ<p><a href=\"http +://getamap.ordnancesurvey.co.uk/getamap/frames.htm?mapAction=zoomabs& +mapX=326643&mapY=672943&zoomLevel=6&isGeo=y\">SHOW OS MAP</a>,</p>\cJ + <p><a href=\"http://www.geo.ed.ac.uk/scotgaz/\cJ \cI\cIfeature +s/featurefirst8976.html\"//" 'extra' => HASH(0x66072c0) 'Point' => HASH(0x6616040) 'id' => 'g8976' 'pos' => '326643,672943' 'srsName' => 'EPSG27700' 'typea' => 'Road or Street' 'typeb' => HASH(0x6616320) empty hash 'typec' => HASH(0x66161f0) empty hash 'xmlns:gml' => 'http://www.opengeospatial.org/standards +/gml' 'name' => ARRAY(0x65e3b00) 0 ' Queen\'s Drive ' 'styleUrl' => '#SGStyle' 2 HASH(0x66196f0) 'Link' => 'http://www.geo.ed.ac.uk/scotgaz/features/featur +efirst7848.html ' 'LookAt' => HASH(0x6616350) 'heading' => 0 'latitude' => 55.94126 'longitude' => '-3.18151' 'range' => 2000 'tilt' => 75 'Point' => HASH(0x6606f30) 'coordinates' => '-3.18151,55.94126,0' 'id' => 'g7848' 'description' => "Located on the west side of Clerk Street +, in the Newington District of Edinburgh, the Queen's Hall represents + the principal venue on the south-side of the city for concerts. Buil +t in 1823 as the Hope Park Chapel of Ease, the building has a two-sto +rey villa frontage, with a tall and slender classical steeple. Latter +ly the Newington and St. Leonard's Church, it was converted into a co +ncert hall in 1979, and opened by Her Majesty Queen Elizabeth II, the + 850-seat auditorium still strongly reflects its ecclesiastical origi +ns, although the pulpit has been replaced by an early 19th Century ch +amber organ. Painted 18th Century panels displaying the Commandments +and the Lord's Prayer, which were brought from the former Buccleuch P +arish Church in 1950, can be seen on the stairs.\cJ\cJNoted particula +rly for its baroque and classical music concerts, the Hall is home to + the world-class Scottish Chamber Orchestra, but also offers a progra +mme of jazz, folk and contemporary music, in addition to theatre, com +edy and opera as well as acting as an important venue for the Edinbur +gh International Festival.\cJ<p><a href=\"http://getamap.ordnancesurv +ey.co.uk/getamap/frames.htm?mapAction=zoomabs&mapX=326298&mapY=672698 +&zoomLevel=6&isGeo=y\">SHOW OS MAP</a>,</p>\cJ <p><a href=\"http:/ +/www.geo.ed.ac.uk/scotgaz/\cJ \cI\cIfeatures/featurefirst7848.html +\"//" 'extra' => HASH(0x6616930) 'Point' => HASH(0x6616c00) 'id' => 'g7848' 'pos' => '326298,672698' 'srsName' => 'EPSG27700' 'typea' => 'Entertainment Venue' 'typeb' => 'Historic Building' 'typec' => HASH(0x6616de0) empty hash 'xmlns:gml' => 'http://www.opengeospatial.org/standards +/gml' 'name' => ARRAY(0x65e3b70) 0 ' Queen\'s Hall, The ' 'styleUrl' => '#SGStyle' 3 HASH(0x6606f20) 'Link' => 'http://www.geo.ed.ac.uk/scotgaz/features/featur +efirst7865.html ' 'LookAt' => HASH(0x6616f40) 'heading' => 0 'latitude' => 55.94259 'longitude' => '-3.17992' 'range' => 2000 'tilt' => 75 'Point' => HASH(0x6616b20) 'coordinates' => '-3.17992,55.94259,0' 'id' => 'g7865' 'description' => "A small district of S Central Edinburgh, + St Leonard's lies a mile (1.5 km) south southeast of the city centre +. The area represented land granted to Holyrood Abbey by King David I + (c.1080 - 1153), and while once being much larger, today is constrai +ned between Holyrood Park Road in the south and Dumbiedykes and the P +leasance in the north. Once associated with brewing, St. Leonard's St +ation was also the terminus of the Innocent Railway. St Leonard's Sch +ool (1879) is now converted into private flats. The Police Headquarte +rs for Central Edinburgh ('A' Division) is located in the modern St. +Leonard's Police Station.\cJ<p><a href=\"http://getamap.ordnancesurve +y.co.uk/getamap/frames.htm?mapAction=zoomabs&mapX=326400&mapY=672800& +zoomLevel=6&isGeo=y\">SHOW OS MAP</a>,</p>\cJ <p><a href=\"http:// +www.geo.ed.ac.uk/scotgaz/\cJ \cI\cIfeatures/featurefirst7865.html\ +"//" 'extra' => HASH(0x661d8f0) 'Point' => HASH(0x661dbc0) 'id' => 'g7865' 'pos' => '326400,672800' 'srsName' => 'EPSG27700' 'typea' => 'Urban District' 'typeb' => HASH(0x661dea0) empty hash 'typec' => HASH(0x661dd70) empty hash 'xmlns:gml' => 'http://www.opengeospatial.org/standards +/gml' 'name' => ARRAY(0x65e3cc0) 0 ' St Leonard\'s ' 'styleUrl' => '#SGStyle' 'name' => ARRAY(0x661e150) 0 'Gazetteer for Scotland: Settlements' 'open' => 0 'xmlns' => 'http://earth.google.com/kml/2.0'
      This encourages me as it appears that I now have a hash of which contains an array of Placemarks and each object in the array (of Placemark) contains a hash(?).

      However I still have the problem that when I try to get the info out of the hash, nothing is returned.
      I tried the use of @places both exactly as you suggested and then substituting $place for @places both time with errors.

      I can understand what is being attempted, namely that you are looking to put the array of Placemarks into an array and then loop through the array and taken values out of the hash contained within?

      All help is great, thanks monks
      Niall