【问题标题】:Linq to XML for KML?用于 KML 的 Linq to XML?
【发布时间】:2008-09-30 02:17:39
【问题描述】:

我是 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.Descendants("Placemark") 给了我一个空枚举。文档已正确加载 - 因为 KML.Descendants 包含每个节点。值得一提的是,这些查询也是空的:

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

有人能指出我正确的方向吗?链接到好的 Linq to XML 教程的加分点——我在网上找到的那些在非常简单的场景中停止。

【问题讨论】:

    标签: vb.net linq-to-xml kml


    【解决方案1】:

    这在 C# 中适用于我:

    XDocument doc = XDocument.Load(@"TheFile.kml");
    
    var q = doc.Descendants().Where(x => x.Name.LocalName == "Placemark"); 
    

    【讨论】:

      【解决方案2】:

      感谢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 documentation

      【讨论】:

        【解决方案3】:

        Scott Hanselman 为寻求基于 C# 的解决方案的人提供了一个简洁的解决方案。

        XLINQ to XML support in 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");
        

        【讨论】:

          【解决方案4】:

          上述修复都没有起到作用;有关详细信息,请参阅我的 cmets。我相信spoon16 和Bruce Murdock 都在正确的轨道上,因为命名空间绝对是问题所在。

          在进一步谷歌搜索后,我在this page 上发现了一些代码,它提出了一种解决方法:只需从原始 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
          

          如果有人可以发布与命名空间一起工作的工作代码而不是核对它,我很乐意给他们答案。

          【讨论】:

            【解决方案5】:

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

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

            忽略任何语法错误,我在 c# 中工作

            您会发现XElement.NameXElement.Name.LocalName/ 之间可能存在差异

            我通常通过文档中的所有XElements foreach 作为第一步,以确保我使用了正确的命名。

            C# 这是我的用法摘录,好像我忘记了 {}

             private string GpNamespace = 
             "{http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions}";
            
             var results = admldoc.Descendants(GpNamespace + 
                           "presentationTable").Descendants().Select(
                            p => new dcPolicyPresentation(p));
            

            【讨论】:

            • 这给我抛出了运行时异常:System.Xml.XmlException - ':' 字符,十六进制值 0x3A,不能包含在名称中。
            • 谢谢 - 这行得通。我找到了一种更简洁的方法,我将在下面发布。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-02-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多