2008-09-30 66 views
6

我是一个LINQ to XML新手,也是一个KML新手;所以忍受着我。Linq到KML的XML?

我的目标是从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( “标”)给我一个空枚举。文档已正确加载 - 因为KML.Descendants包含每个节点。对于什么是值得的这些查询也是空的:

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

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

回答

1

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

注意:克以下中的第一行的xmlns。这为您提供了在其他地方引用此名称空间的快捷方式。

有关XNamespace类的更多信息,请参见MSDN documentation

0

您可能需要一个命名空间添加到的XElement名

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

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

你会发现可能存在VS XElement.Name.LocalName/

XElement.Name差异

我通常会将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)); 
+0

这给了我 运行时抛出异常信息:System.Xml.XmlException - 在 ':' 字符,十六进制值0x3A,不能包含在一个名字。 – 2008-09-30 02:54:01

0

无论上述修复做的工作;请参阅我的评论了解详情。我相信spoon16和布鲁斯默多克都走在正确的轨道上,因为命名空间绝对是问题。

进一步谷歌搜索后,我偶然发现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 

如果任何人都可以发布与命名空间一起工作的工作代码,而不是将其加入,我会很乐意给他们答案。

1

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"); 
5

这对我的作品在C#:

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

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