Linq to XML pour KML?
-
02-07-2019 - |
Question
Je suis un novice LINQ to XML, et un novice KML également; alors sois indulgent avec moi.
Mon objectif est d’extraire des repères individuels à partir d’un fichier KML. Mon KML commence ainsi:
<?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>
...
C’est ce que j’ai eu:
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
Jusqu'à présent, rien de bon - Kml.Descendants (& "; Placemark &";) me donne une énumération vide. Le document est chargé correctement, car KML.Descendants contient tous les nœuds. Pour ce que cela vaut, ces requêtes sont également vides:
Dim foo = Kml.Descendants("Document")
Dim foo = Kml.Descendants("Folder")
Quelqu'un peut-il me diriger dans la bonne direction? Des points bonus pour les liens vers de bons tutoriels Linq to XML - ceux que j'ai trouvés en ligne s'arrêtent à des scénarios très simples.
La solution 2
Merci à spoon16 et à Bruce Murdock de m'avoir orienté dans la bonne direction. Le code que spoon16 a publié fonctionne, mais vous oblige à concaténer l’espace de nommage avec le nom de chaque élément, ce qui n’est pas aussi propre que je le souhaiterais.
J'ai fait un peu plus de recherches et j'ai compris comment cela est supposé être fait - c'est très concis et j'adore le nouveau < ... > syntaxe crochet pour faire référence aux éléments 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
Notez le : g qui suit les xmlns de la première ligne. Cela vous donne un raccourci pour faire référence à cet espace de noms ailleurs.
Pour plus d'informations sur la classe XNamespace, consultez la . Documentation MSDN .
Autres conseils
Cela fonctionne pour moi en C #:
XDocument doc = XDocument.Load(@"TheFile.kml");
var q = doc.Descendants().Where(x => x.Name.LocalName == "Placemark");
Scott Hanselman a une solution concise pour ceux qui recherchent une solution basée sur C #.
Prise en charge de XLINQ vers XML dans VB9
De plus, utiliser XNamespace est pratique, au lieu d’ajouter une chaîne. C’est un peu plus formel.
// 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");
Aucune des solutions ci-dessus n'a été efficace. voir mes commentaires pour plus de détails. Je pense que Spoon16 et Bruce Murdock sont sur la bonne voie, car l’espace de nommage est définitivement le problème.
Après avoir cherché Google, je suis tombé sur du code sur cette page suggérant une solution de contournement: supprimez simplement l'attribut xmlns du code XML d'origine.
' 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 quelqu'un peut publier un code de travail qui fonctionne avec l'espace de noms au lieu de le modifier, je lui donnerai volontiers la réponse.
Vous devrez peut-être ajouter un espace de nom au nom XElement
Dim ns as string = "http://earth.google.com/kml/2.0"
dim foo = Kml.Descendants(ns + "Document")
ignorer les erreurs de syntaxe, je travaille en c #
Vous constaterez qu'il peut y avoir une différence entre XElement.Name
et XElement.Name.LocalName/
Je passe habituellement foreach
dans tout le XElements
de la documentation, dans un premier temps, pour m'assurer que j'utilise le bon nom.
C # Voici un extrait de mon utilisation, on dirait que j'ai oublié le {}
private string GpNamespace =
"{http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions}";
var results = admldoc.Descendants(GpNamespace +
"presentationTable").Descendants().Select(
p => new dcPolicyPresentation(p));