How to parse KML files with perl?

I am trying to parse a KML file using perl. I am trying to use the XML::Simple module for this.

I want to go through each placemarker and extract some data, namely

1) Maked
2) coordinates

After reading a few posts, I tried the following just to print the coordinates of all the points, but this failed

 use strict; use warnings; use XML::Simple; use Data::Dumper; my $myFile = XMLin('ExperimentMap.kml'); foreach my $folder (@{$myFile->{Document}->{Folder}->{Placemark}}) { print $folder->{Point}->{coordinates}."\n"; } 

I am using the following KML:

 <?xml version='1.0' encoding='UTF-8'?> <kml xmlns='http://www.opengis.net/kml/2.2'> <Document> <name>ExperimentMap</name> <description><![CDATA[]]></description> <Folder> <name>ExperimentLayer</name> <Placemark> <styleUrl>#icon-503-FF8277</styleUrl> <name>home</name> <ExtendedData> <Data name='string'> <displayName>Mcode</displayName> <value>PLAAB</value> </Data> </ExtendedData> <ExtendedData> <Data name='string'> <displayName>postal code</displayName> <value>450010</value> </Data> </ExtendedData> <description><![CDATA[my home Mcode: PLAAB postal code: 450010]]></description> <Point> <coordinates>80.23435592651367,13.094024942328286,0.0</coordinates> </Point> </Placemark> <Placemark> <styleUrl>#icon-503-FF8277</styleUrl> <name>shop</name> <ExtendedData> <Data name='string'> <displayName>Mcode</displayName> <value>XMPLE</value> </Data> </ExtendedData> <ExtendedData> <Data name='string'> <displayName>postal code</displayName> <value>450013</value> </Data> </ExtendedData> <description><![CDATA[my shop Mcode: XMPLE postal code: 450013]]></description> <Point> <coordinates>80.2437973022461,13.106230102044576,0.0</coordinates> </Point> </Placemark> <Placemark> <styleUrl>#icon-503-FF8277</styleUrl> <name>place3</name> <ExtendedData> <Data name='string'> <displayName>Mcode</displayName> <value>UDKBL</value> </Data> </ExtendedData> <ExtendedData> <Data name='string'> <displayName>postal code</displayName> <value>578635</value> </Data> </ExtendedData> <description><![CDATA[my school Mcode: UDKBL postal code: 578635]]></description> <Point> <coordinates>80.24688720703125,13.096198508196448,0.0</coordinates> </Point> </Placemark> </Folder> <Style id='icon-503-FF8277'> <IconStyle> <color>ff7782FF</color> <scale>1.1</scale> <Icon> <href>http://www.gstatic.com/mapspro/images/stock/503-wht-blank_maps.png</href> </Icon> </IconStyle> </Style> </Document> </kml> 
+4
source share
3 answers

What about:

 while (my ($key, $folder) = each %{$myFile->{Document}{Folder}{Placemark}}) { print $folder->{Point}->{coordinates}."\n"; } 

output:

 80.2437973022461,13.106230102044576,0.0 80.24688720703125,13.096198508196448,0.0 80.23435592651367,13.094024942328286,0.0 

In your code you use

 foreach my $folder (@{$myFile->{Document}->{Folder}->{Placemark}}) { print $folder->{Point}->{coordinates}."\n"; } 

Assuming $myFile->{Document}->{Folder}->{Placemark} is an array reference. But this is not so, this is a reference to the hash, so you need to go through it, and the foreach (key, value) pair, extract the coordinate from the value.

+3
source

I don’t think I would use XML :: Simple for this.

With XML :: Twig, this is what you could write:

 #!/usr/bin/perl use strict; use warnings; use 5.10.0; # to get 'say' use XML::Twig; XML::Twig->new( twig_roots => { coordinates => sub { say $_->text; } }) ->parsefile( $ARGV[0]); 
+3
source

Another possibility is to use XML::LibXML and XPaths. The advantage of XPaths is that they are also available in other languages, so another developer can understand your code. The disadvantage of XPaths is that their use is not more pleasant in the presence of namespaces (which is the case here), which leads to some ugly workarounds, such as using the local-name () function.

Here's an example script:

 use XML::LibXML; my $doc = XML::LibXML->new->parse_file('ExperimentMap.kml'); for my $coordinate_node ($doc->findnodes('//*[local-name()="coordinates"]')) { print $coordinate_node->textContent, "\n"; } 
0
source

Source: https://habr.com/ru/post/1487431/


All Articles