Pregunta

Soy un novato de LINQ to XML, y también un novato de KML; así que tengan paciencia conmigo.

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 lo más lejos que he llegado:

    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 ahora no es bueno - Kml. Descendientes (" Marca 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, estas consultas también aparecen vacías:

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

¿Alguien puede señalarme en la dirección correcta? Los 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.

¿Fue útil?

Solución 2

Gracias a spoon16 y Bruce Murdock por señalarme en la dirección correcta. El código que cuchara16 publicó 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 buscado un poco más y he descubierto cómo se supone que debe hacerse esto: es súper conciso, y me encanta el nuevo < ... > sintaxis de paréntesis para referirse a 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

Tenga en cuenta que : g sigue los xmlns en la primera línea. Esto le brinda un acceso directo para hacer referencia a este espacio de nombres en otro lugar.

Para obtener más información sobre la clase XNamespace, consulte Documentación de MSDN .

Otros consejos

Esto funciona para mí en C #:

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

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

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

Soporte XLINQ a XML en VB9

Además, usar XNamespace es útil, en lugar de solo agregar 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");

Ninguna de las soluciones 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 esta página que sugirió una solución alternativa: simplemente elimine 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 alguien puede publicar un código de trabajo que funcione con el espacio de nombres en lugar de eliminarlo, con gusto le daré la respuesta.

Es posible que deba agregar un espacio de nombres al nombre XElement

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

ignorar cualquier error de sintaxis, trabajo en c #

Encontrará que puede haber una diferencia en XElement.Name vs XElement.Name.LocalName/

Usualmente foreach a través de todos los XElements en el documento como primer paso para asegurarme de que estoy usando el nombre correcto.

C # Aquí hay un extracto de mi uso, parece que 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));
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top