KML的Linq to XML?

6

我是一个LINQ to XML的新手,也是KML的新手;所以请谅解我的生疏。

我的目标是从一个KML文件中提取单独的Placemark。我的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.Descendants("Placemark") 给我返回一个空的枚举。文档已经正确加载 - 因为 KML.Descendants 包含了每个节点。可能对你有用的是,这些查询也是空的:

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

有人能指点我正确的方向吗?如果能提供好的Linq to XML教程链接,那就更好了——我在网上找到的教程只涵盖了非常简单的场景。

5个回答

6

这对我在C#中有效:

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

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

1
感谢 spoon16 和 Bruce Murdock 指引我正确的方向。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

请注意第一行xmlns后面的:g。这为您提供了一个快捷方式,以便在其他地方引用此命名空间。
有关XNamespace类的更多信息,请参阅MSDN文档

1

Scott Hanselman针对那些寻找基于C#的解决方案的人提出了一个简明的解决方案。

VB9中的XLINQ to XML支持

此外,使用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");

0

以上的修复方法都没有起作用,详见我的评论。我认为spoon16和Bruce Murdock都在正确的轨道上,因为命名空间确实是问题所在。

经过进一步的谷歌搜索,我在这个页面上找到了一些代码,建议采用一个解决方法:只需从原始XML中删除xmlns属性即可。

    ' 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

如果有人可以发布可以使用名称空间而不是将其销毁的工作代码,我将很乐意给他们答案。

0

你可能需要为XElement名称添加命名空间

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

忽略任何语法错误,我使用C#工作

你会发现XElement.NameXElement.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));

1
这给了我一个运行时异常:System.Xml.XmlException - 冒号字符,十六进制值0x3A,不能包含在名称中。 - Herb Caudill
谢谢,这个可行。我找到了一个更简洁的方法,我会在下面发布。 - Herb Caudill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接