即使XDocument中有内容,XDocument.Descendants()也是空的

时间:2013-06-09 16:11:12

标签: xml linq-to-xml kml

我正在加载此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 DOES加载文件,就像我在调试器中观察它一样,我可以看到它包含完整的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吗?

1 个答案:

答案 0 :(得分: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() [sic],我希望得到所有的后代。

FirstNode给出非空答案的原因是您无法使用参数更改其行为,因此无法避免正确调用它。

发布您的实际代码

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

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

如果您创建了SSCCE,我可以帮助您。 (我不知道)。但至少我们可以用精确的术语表达你的问题。

更新: 既然你没有发布任何代码,我会猜测是什么问题: 你的后代()和元素()实际上包含节点,但你没有正确地询问它们。 如果您发布了代码,我会花更少的时间给您答案。

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

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

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” - 它可能在技术上是正确的但是误导性。你的screencap(+按钮)表明枚举有孩子。

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