Herb Caudill Herb Caudill - 2 months ago 12
Vb.net Question

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.

Answer

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.

Comments