6

我是 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 教程的加分点——我在网上找到的那些在非常简单的场景中停止。

4

5 回答 5

6

这在 C# 中对我有用:

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

var q = doc.Descendants().Where(x => x.Name.LocalName == "Placemark"); 
于 2009-09-29T17:43:58.080 回答
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 文档

于 2008-09-30T14:26:15.590 回答
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");
于 2008-10-21T20:39:29.693 回答
0

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

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

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

XElement.Name你会发现vs可能有区别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));
于 2008-09-30T02:33:56.363 回答
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

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

于 2008-09-30T14:01:36.710 回答