Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq to XML for KML?

I'm a LINQ to XML newbie, and a KML newbie as well; so bear with me.

My goal is to extract individual Placemarks from a KML file. My KML begins thusly:

<?xml version="1.0" encoding="utf-8"?>
<Document xmlns="http://earth.google.com/kml/2.0">
  <name>Concessions</name>
  <visibility>1</visibility>
  <Folder>
    <visibility>1</visibility>
    <Placemark>
      <name>IN920211</name>
      <Style>
        <PolyStyle>
          <color>80000000</color>
        </PolyStyle>
      </Style>
      <Polygon>
        <altitudeMode>relativeToGround</altitudeMode>
        <outerBoundaryIs>
          <LinearRing>
            <coordinates>11.728374,1.976421,0 11.732967,1.965322,0 11.737225,1.953161,0 11.635858,1.940812,0 11.658102,1.976874,0 11.728374,1.976421,0 </coordinates>
          </LinearRing>
        </outerBoundaryIs>
      </Polygon>
    </Placemark>
    <Placemark>
    ...

This is as far as I've gotten:

    Dim Kml As XDocument = XDocument.Load(Server.MapPath("../kmlimport/ga.kml"))
    Dim Placemarks = From Placemark In Kml.Descendants("Placemark") _
         Select Name = Placemark.Element("Name").Value

So far no good - Kml.Descendants("Placemark") gives me an empty enumeration. The document is loaded properly - because KML.Descendants contains every node. For what it's worth these queries come up empty as well:

Dim foo = Kml.Descendants("Document") 
Dim foo = Kml.Descendants("Folder") 

Can someone point me in the right direction? Bonus points for links to good Linq to XML tutorials - the ones I've found online stop at very simple scenarios.

like image 791
Herb Caudill Avatar asked Sep 30 '08 02:09

Herb Caudill


2 Answers

This works for me in C#:

XDocument doc = XDocument.Load(@"TheFile.kml");

var q = doc.Descendants().Where(x => x.Name.LocalName == "Placemark"); 
like image 132
Jacob Avatar answered Sep 27 '22 21:09

Jacob


Thanks to spoon16 and Bruce Murdock for pointing me in the right direction. The code that spoon16 posted works, but forces you to concatenate the namespace with every single element name, which isn't as clean as I'd like.

I've done a bit more searching and I've figured out how this is supposed to be done - this is super concise, and I love the new <...> bracket syntax for referring to XML elements.

Imports <xmlns:g='http://earth.google.com/kml/2.0'>
Imports System.Xml.Linq

 ...

    Dim Kml As XDocument = XDocument.Load(Server.MapPath("../kmlimport/ga.kml"))
    For Each Placemark As XElement In Kml.<g:Document>.<g:Folder>.<g:Placemark>
        Dim Name As String = Placemark.<g:name>.Value
    Next

Note the :g following the xmlns in the first line. This gives you a shortcut to refer to this namespace elsewhere.

For more about the XNamespace class, see the MSDN documentation.

like image 38
Herb Caudill Avatar answered Sep 27 '22 22:09

Herb Caudill