【问题标题】:XDocument.Descendants() is empty even though there is content in the XDocumentXDocument.Descendants() 为空,即使 XDocument 中有内容
【发布时间】:2013-06-09 16:11:11
【问题描述】:

我正在加载此 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 吗?

【问题讨论】:

  • 不确定是否重要,但 XDocument 的 DocumentType 也为空。
  • 事实证明 xDoc.Nodes() 也是空的,即使 xDoc.FirstNode 返回文档中第一个节点的 XNode ...... gah wtf!
  • ((XElement)xDoc.FirstNode 没有平衡括号。发布您的代码以获取最小的失败示例并指示值(例如通过打印)可能很有用。可能是您错误地投射元素
  • 抱歉,这只是我帖子中的错字,而不是原始代码,已在上面修复。没有太多要发布的代码,我确实做了 XDocument.Load 然后 xDoc.Descendants() 是空的
  • ((XElement)xDoc.FirstNode) 返回什么?我希望有“kml”元素,但距离我使用 LINQ 已经有一段时间了。

标签: xml linq-to-xml kml


【解决方案1】:

我现在将其转为答案。

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)“简短、自包含、正确(可编译)、示例。”

您应该做的是创建一个 SMALL 示例。我会使用您的 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 行)。小型 sn-p (SSCCE) 的价值在于它可以立即被其他人复制——他们可以在自己的系统中进行剪切、粘贴和运行。代码及其错误比调试器要精确得多。顺便说一句,我希望您正在使用单元测试和测试驱动开发 - 如果您创建了一个失败的测试,那么问题出在哪里就很清楚了。

【讨论】:

  • 您说“如果您使用 Descendants(),我希望得到所有后代”,这也是我所期望的。我按照您的要求发布了代码,但就像我说的那样,我实际上只是加载文档并检查 XDocument 的后代。如果我查看 XDocument 的内容,确实所有的 xml 内容都在那里,但无论我尝试什么,我都无法从 Descendants 那里得到任何东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
  • 2010-12-05
  • 1970-01-01
  • 2012-02-16
  • 1970-01-01
相关资源
最近更新 更多