【问题标题】:iterating XElements and then using XPath to extract child element values gets wrong value迭代 XElements,然后使用 XPath 提取子元素值得到错误值
【发布时间】:2026-01-23 02:10:01
【问题描述】:

我有两种方法:

  • 第一个将 xml 字符串解析为一些 XElement(其中 xml 是“香蕉”元素的序列)
  • 第二个从子 'id' 元素中提取值并将其返回

我有两个“GetBananaId(XElement element)”的替代实现 - 谁能解释为什么第二个“错误”实现没有给出相对于其 XElement 参数的子元素?

public void TestHarness()
{
    var xml = "<bananas><banana><id>A</id></banana><banana><id>B</id></banana><banana><id>C</id></banana></bananas>";
    foreach (var element in GetBananaElements(xml))
    {
        var right = GetBananaId(element);
        var wrong = GetBananaId_WRONG(element);
        Console.WriteLine("Right: {0}, Wrong: {1}", right, wrong);
    }
}

public IEnumerable<XElement> GetBananaElements(string recordsXml)
{
    var recordsXDoc = XDocument.Parse(recordsXml);
    return recordsXDoc.XPathSelectElements("//banana");
}

public string GetBananaId(XElement element)
{
    return element.Element("id").Value;
}

public string GetBananaId_WRONG(XElement element)
{
    return element.XPathSelectElement("//id").Value;
}

这些产生控制台输出:

Right: A, Wrong: A
Right: B, Wrong: A
Right: C, Wrong: A

【问题讨论】:

    标签: .net linq-to-xml xelement


    【解决方案1】:

    使用相对路径return element.XPathSelectElement("id").Value;,使用//id/ 向下搜索,这是文档节点。

    【讨论】:

    • 感谢 Martin - 解决了这个问题。为了完全回答我的问题,我真的很想知道为什么会这样:我在 XElement 上调用 XPathSelectElement("//id"),但这种行为表明此方法实际上看到了完整文档的 DOM?
    • 是的,当然,XPath 允许您在文档中导航,您不仅可以选择上下文节点的子节点或后代节点,还可以选择其祖先、兄弟姐妹、文档节点。如果您想要foo 子元素使用路径foo./foo,对于后代使用.//foodescendant::foo。如果使用/,则选择上下文节点的文档节点,并且任何以/ 开头的路径都从文档节点开始搜索,因此//id 选择上下文节点的文档节点的所有id 后代。跨度>
    • 因此,当调用 XPathSelectElement 时,调用它的对象只是为您的 XPath 表达式设置上下文节点; XPath 表达式仍然可以访问上下文节点所在的完整文档。这是有道理的——我对 XPath 有了更多的了解——谢谢。