2008-09-30 25 views
6

Soy un novato LINQ to XML y un novato KML también; así que tengan paciencia conmigo.Linq a XML para KML?

Mi objetivo es extraer marcas de posición individuales de un archivo KML. Mi KML comienza así:

<?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> 
    ... 

Esto es por lo que yo he conseguido:

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 

Hasta el momento no hay buenos - Kml.Descendants ("marcas de posición") me da una enumeración vacía. El documento se carga correctamente, porque KML.Descendants contiene todos los nodos. Por lo que vale la pena estas consultas con las manos vacías, así:

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

Puede alguien me punto en la dirección correcta? Puntos de bonificación por enlaces a buenos tutoriales de Linq a XML: los que he encontrado en línea se detienen en escenarios muy simples.

Respuesta

1

Gracias a spoon16 y Bruce Murdock por señalarme en la dirección correcta. El código que publicó spoon16 funciona, pero te obliga a concatenar el espacio de nombres con cada nombre de elemento, que no es tan limpio como me gustaría.

He hecho un poco más de búsqueda y he descubierto cómo se supone que debe hacerse, esto es súper conciso, y me encanta la nueva sintaxis del parche < ...> para referirse a los elementos XML.

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 

Nota la : g siguiendo las xmlns en la primera línea. Esto le da un atajo para referirse a este espacio de nombre en otro lugar.

Para obtener más información acerca de la clase XNamespace, consulte el MSDN documentation.

0

Es posible que necesite añadir un espacio de nombres para el nombre XElement

Dim ns as string = "http://earth.google.com/kml/2.0" 
dim foo = Kml.Descendants(ns + "Document") 

ignoran los errores de sintaxis, trabajo en C#

Usted encontrará que puede haber una diferencia en el XElement.Name vs XElement.Name.LocalName/

Yo usualmente foreach a través de todos los XElements en el documento como un primer paso para asegurarme de que estoy usando la correcta denominación.

C# Aquí es un extracto de mi uso, parece que se me olvidó el {}

private string GpNamespace = 
"{http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions}"; 

var results = admldoc.Descendants(GpNamespace + 
       "presentationTable").Descendants().Select(
       p => new dcPolicyPresentation(p)); 
+0

Esto me da excepción en tiempo de ejecución arrojado: System.Xml.XmlException - La ':' carácter, valor hexadecimal 0x3A, no pueden ser incluidos en un nombre. –

+0

Siéntase libre de responder en C#. –

+0

Gracias - esto funciona. He encontrado un enfoque más conciso que publicaré a continuación. –

0

Ninguna de las correcciones anteriores hizo el trabajo; ver mis comentarios para más detalles. Creo que tanto spoon16 como Bruce Murdock están en el camino correcto, ya que el espacio de nombres es definitivamente el problema.

Después de buscar en Google encontré un código en this page que sugería una solución alternativa: simplemente quita el atributo xmlns del XML original.

' Read raw XML 
    Dim RawXml As String = ReadFile("../kmlimport/ga.kml") 
    ' HACK: Linq to XML choking on the namespace, just get rid of it 
    RawXml = RawXml.Replace("xmlns=""http://earth.google.com/kml/2.0""", "") 
    ' Parse XML 
    Dim Kml As XDocument = XDocument.Parse(RawXml) 
    ' Loop through placemarks 
    Dim Placemarks = From Placemark In Kml.<Document>.<Folder>.Descendants("Placemark") 
    For Each Placemark As XElement In Placemarks 
     Dim Name As String = Placemark.<name>.Value 
     ... 
    Next 

Si cualquiera puede publicar el código que funciona con el espacio de nombres en lugar de atacar con armas nucleares que funcione, con mucho gusto les daré la respuesta.

1

Scott Hanselman tiene una solución concisa para aquellos que buscan una solución basada en C#.

XLINQ to XML support in VB9

Además, el uso XNamespace viene muy bien, en lugar de simplemente añadiendo una cadena. Esto es un poco más formal.

// This code should get all Placemarks from a KML file    
var xdoc = XDocument.Parse(kmlContent); 
XNamespace ns = XNamespace.Get("http://earth.google.com/kml/2.0"); 
var ele = xdoc.Element(ns + "kml").Element(ns + "Document").Elements(ns + "Placemark"); 
5

Esto funciona para mí en C#:

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

var q = doc.Descendants().Where(x => x.Name.LocalName == "Placemark");