1

我正在加载这个 KML:http ://www.mcallen.net/Files/docs/traffic/bike/kml/McBikeRoutes.kml

进入 XDocument,如果我在调试器中查看 XDocument,它似乎正确地填充了文件的内容。

但是,当我尝试访问任何后代时,无论我做什么,它都是空的。

    var xDoc = XDocument.Load("Assets/McBikeRoutes.kml");
    var d = xDoc.Descendants(); // <-- Empty result

在上面的代码中,McBikeRoutes.kml 是上面链接文件的精确副本,我只是手动将它添加到我的项目中,因此它是在内部而不是在线获取它。

此外,我可以验证 xDoc 是否加载了文件,就好像我在调试器中观察它一样,我可以看到它包含完整的 KML 文档内容。

但是,无论我如何尝试访问后代,结果始终为空。

我尝试在文档中包含默认命名空间和所有其他命名空间,但无论我做什么都没有结果。

我终于尝试 xDoc.Descendants() 来获取所有内容,结果也为空!

我尝试了 xDoc.Root.Descendants() 和 xDoc.Document.Descendants(),以及 xDoc.Elements()、xDoc.Root.Elements() 和 xDoc.Document.Elements() 并且 EVERTHING 返回一个空结果,甚至尽管 XDocument 中显然有信息。

奇怪的是,如果我这样做:

((XElement)xDoc.FirstNode)

我确实得到了第一个后代 XElement!但如果我这样做:

((XElement)xDoc.FirstNode).Descendants()

我仍然没有得到任何结果(当我尝试 Elements() 时也是如此)!

有人知道我在这里做错了什么吗?是因为文档是 KML 吗?

4

1 回答 1

0

我现在将其转移到答案。

Descendants() 有两种方法 http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.descendants.aspx

Public method   Descendants()   
   Returns a collection of the descendant elements for this document or element, 
   in document order. (Inherited from XContainer.)
Public method   Descendants(XName)  
   Returns a filtered collection of the descendant elements for this 
   document or element, in document order. Only elements that have a 
   matching XName are included in the collection. (Inherited from XContainer.)

如果你Descendants(XName)用错误的参数调用,你很可能不会得到后代。如果你使用Descendants()[原文如此],我希望得到所有后代。

FirstNode给出非空答案的原因是你不能用参数改变它的行为,所以你不能避免正确地调用它。

发布您的实际代码

更新。这种讨论不是解决问题的最有效方法。您应该构建一个 SSCCE ( https://meta.stackexchange.com/questions/22754/sscce-how-to-provide-examples-for-programming-questions)“简短、自包含、正确(可编译)、示例。”

你应该做的是创建一个小例子。我会使用您的 KML 文件并创建可以读取的最小有效子集,并且您可以在其中明确显示您认为失败的方法。(顺便说一句,我认为问题极不可能是 KML - 我认为这是您调用方法的方式和或您所期望的)。我会尝试读取 XML 字符串,以便将其发布在 SO 上,并提供您正在使用的完整代码以及您实际得到的代码。诸如“空”之类的词不够精确 - 这是否意味着 IEnumeration 具有某些函数报告的零元素?(我对 XDocument 的了解已经有几年了)。

如果您创建 SSCCE,我可能会为您提供帮助。(我不知道)。但至少我们可以准确地表达您的问题。

更新:由于您没有发布任何代码,我将猜测出了什么问题:您的 Descendants() 和 Elements() 实际上包含节点,但您没有正确询问它们。如果你发布了代码,我会花更少的时间给你一个答案。

更新感谢调试器快照。我猜想这就是问题最初表现出来的地方。首先,您必须使用精确的术语——您编写了“空”,但调试器将其标记为“空”。它们是完全不同的,将一个用于另一个会误导。

我的怀疑是并且是您无法使用调试器来显示后代元素。我认为您和您的调试器彼此不了解。这是不可能通过网络调试的。

Descendants() 是一个 IEnumerable:

public IEnumerable<XElement> Descendants()

我的 C# /Linq 生锈了,我没有工作系统,但总的来说,这意味着它提供了按顺序获取元素的方法。它唯一的方法是:

GetEnumerator() ( http://msdn.microsoft.com/en-us/library/s793z9y2.aspx )

您将必须弄清楚如何在 CODE(而不是调试器)中获取后代,因此您需要学习如何遍历 IEnumerable。根据记忆,这将是这样的:

foreach (XElement descendant : getDescendants()) {
    printSomehowOrDoSomething(descendant);
}

如果您编写要使用的实际代码并运行它,那么它要么会做您想做的事,要么您会对您可以交流的问题有一个更清晰的想法。(我不知道为什么您的调试器说“null” - 它在技术上可能是正确的但具有误导性。您的屏幕截图(+ 按钮)也表明枚举有孩子。

简单:忘记调试器(它不是代码)并编写您想要执行的代码,尽可能简单地在第一个实例中(不超过 10 行)。小片段 (SSCCE) 的价值在于它可以立即被其他人复制 - 他们可以剪切、粘贴并在自己的系统中运行。代码及其错误比调试器要精确得多。顺便说一句,我希望您正在使用单元测试和测试驱动开发——如果您创建了一个失败的测试,那么问题出在哪里就很清楚了。

于 2013-06-09T18:42:35.547 回答