Вопрос
Я новичок в LINQ to XML, а также новичок в KML;так что потерпи меня.
Моя цель - извлечь отдельные метки из файла KML.Мой KML начинается так:
<?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>
...
Это все, что я успел узнать:
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
Пока ничего хорошего - Kml.Потомки ("Метка места") дают мне пустое перечисление.Документ загружен правильно - потому что KML.Descendants содержит каждый узел.Как бы то ни было, эти запросы также оказываются пустыми:
Dim foo = Kml.Descendants("Document")
Dim foo = Kml.Descendants("Folder")
Кто-нибудь может указать мне правильное направление?Бонусные баллы за ссылки на хорошие руководства по Linq to XML - те, что я нашел в Интернете, останавливаются на очень простых сценариях.
Решение 2
Спасибо spoon16 и Брюсу Мердоку за то, что указали мне правильное направление.Код, опубликованный spoon16, работает, но заставляет вас объединять пространство имен с каждым отдельным именем элемента, что не так чисто, как хотелось бы.
Я еще немного поискал и понял, как это должно быть сделано - это очень лаконично, и мне нравится новое <...> синтаксис скобок для ссылки на 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
Обратите внимание на :g следуя за xmln в первой строке.Это дает вам ярлык для обращения к этому пространству имен в другом месте.
Подробнее о классе XNamespace см. Документация MSDN.
Другие советы
Это работает для меня на C#:
XDocument doc = XDocument.Load(@"TheFile.kml");
var q = doc.Descendants().Where(x => x.Name.LocalName == "Placemark");
У Скотта Хансельмана есть краткое решение для тех, кто ищет решение на основе C #.
Поддержка преобразования XLINQ в XML в VB9
Кроме того, удобно использовать XNamespace, а не просто добавлять строку.Это немного более формально.
// 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");
Ни одно из вышеперечисленных исправлений не помогло;подробности смотрите в моих комментариях.Я считаю, что и spoon16, и Брюс Мердок находятся на правильном пути, поскольку пространство имен определенно является проблемой.
После дальнейшего поиска в Google я наткнулся на некоторый код на эта страница это наводило на мысль об обходном пути:просто удалите атрибут xmlns из исходного XML-файла.
' 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
Если кто-нибудь может опубликовать рабочий код, который работает с пространством имен вместо того, чтобы уничтожать его, я с радостью дам им ответ.
Возможно, вам потребуется добавить пространство имен к имени XElement
Dim ns as string = "http://earth.google.com/kml/2.0"
dim foo = Kml.Descendants(ns + "Document")
игнорируйте любые синтаксические ошибки, я работаю на c#
Вы обнаружите, что может быть разница в XElement.Name
против XElement.Name.LocalName/
Я обычно foreach
через все XElements
в документе в качестве первого шага, чтобы убедиться, что я использую правильное именование.
C# Вот выдержка из моего использования, похоже, я забыл {}
private string GpNamespace =
"{http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions}";
var results = admldoc.Descendants(GpNamespace +
"presentationTable").Descendants().Select(
p => new dcPolicyPresentation(p));