Domanda

Sono un principiante di LINQ to XML e anche un principiante di KML; quindi abbi pazienza.

Il mio obiettivo è quello di estrarre singoli segnaposto da un file KML. Il mio KML inizia così:

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

Questo è quanto ho ottenuto:

    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

Finora non va bene - Kml.Descendants (" Placemark ") mi dà un elenco vuoto. Il documento viene caricato correttamente, poiché KML.Descendants contiene tutti i nodi. Per quello che vale, anche queste domande risultano vuote:

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

Qualcuno può indicarmi la giusta direzione? I punti bonus per i collegamenti a buoni tutorial da Linq a XML - quelli che ho trovato online si fermano in scenari molto semplici.

È stato utile?

Soluzione 2

Grazie a spoon16 e Bruce Murdock per avermi indicato nella giusta direzione. Il codice pubblicato da spoon16 funziona, ma ti costringe a concatenare lo spazio dei nomi con ogni singolo nome di elemento, che non è pulito come vorrei.

Ho fatto un po 'più di ricerca e ho capito come dovrebbe essere fatto - questo è super conciso e adoro il nuovo < ... > sintassi della parentesi per il riferimento a elementi 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 : g seguendo gli xmlns nella prima riga. Questo ti dà una scorciatoia per fare riferimento a questo spazio dei nomi altrove.

Per ulteriori informazioni sulla classe XNamespace, vedere Documentazione MSDN .

Altri suggerimenti

Questo funziona per me in C #:

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

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

Scott Hanselman ha una soluzione concisa per chi cerca una soluzione basata su C #.

Supporto da XLINQ a XML in VB9

Inoltre, usare XNamespace è utile, piuttosto che aggiungere semplicemente una stringa. Questo è un po 'più formale.

// 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");

Nessuna delle correzioni precedenti ha fatto il lavoro; vedere i miei commenti per i dettagli. Credo che spoon16 e Bruce Murdock siano sulla buona strada, dal momento che lo spazio dei nomi è sicuramente il problema.

Dopo ulteriori ricerche su Google ho trovato del codice su questa pagina che ha suggerito una soluzione alternativa: basta rimuovere l'attributo xmlns dall'XML originale.

    ' 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

Se qualcuno può pubblicare un codice funzionante che funziona con lo spazio dei nomi invece di modificarlo, li darò volentieri la risposta.

Potrebbe essere necessario aggiungere uno spazio dei nomi al nome XElement

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

ignoro eventuali errori di sintassi, lavoro in c #

Scoprirai che potrebbe esserci una differenza tra XElement.Name vs XElement.Name.LocalName/

Di solito foreach attraverso tutti i XElements nel documento come primo passo per essere sicuro di usare il nome giusto.

C # Ecco un estratto del mio utilizzo, sembra che abbia dimenticato il {}

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

 var results = admldoc.Descendants(GpNamespace + 
               "presentationTable").Descendants().Select(
                p => new dcPolicyPresentation(p));
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top