如何使用 LINQ 在 XML 中按名称获取元素

Posted

技术标签:

【中文标题】如何使用 LINQ 在 XML 中按名称获取元素【英文标题】:How to get elements by name in XML using LINQ 【发布时间】:2011-05-07 08:18:40 【问题描述】:

我在这里选择了标题,因为我的问题是我需要获取示例中提到的 Item 节点。 我有以下 XML 并且在使用 LINQ 查询它时遇到问题,我之前能够解析 XML - 但是我已经坚持了几个小时,希望有人能提供帮助。 下面是我的 XML 数据(示例数据):

<a:entry
    xmlns:a="http://www.w3.org/2005/Atom">
    <a:id>98765</a:id>
    <info>Data Catalogue</info>
    <data>
        <items>
            <item>
                <id>123456</id>
                <value>Item One</value>
            </item>
            <item>
                <id>654321</id>
                <value>Item Two</value>
            </item>
        </items>
    </data>
    <items>
        <item>
            <id>123456</id>
            <value>Item One</value>
        </item>
        <item>
            <id>654321</id>
            <value>Item Two</value>
        </item>
    </items>
    <a:author>
        <a:name>Catalogue</a:name>
    </a:author>
</a:entry>

我希望能够从 Items 下的 Item XML 标签中提取 ID,但是在 data 下有一个 Items 标签,其中包含 Item 条目我根本不想要这些节点 - 我想要 root/items/id/id 如果这被表示为路径。我已经使用 LINQ 尝试了我所知道的一切,所以如果有人可以提供帮助,请注意尽管这是基于系统的示例数据 - 格式无法更改,因此这不是一个可接受的解决方案。 我似乎无法确定哪里出错了 - 我尝试的每个 LINQ 表达式都没有返回任何内容,我认为命名空间是一个问题,并试图整合它,但我正在绕圈子。 解决方案必须在 Silverlight 和 C# 中工作

我尝试了以下方法:

IEnumerable<XElement> nodes =
    element.Elements().Where(e => e.Name.LocalName == "items")

但是,这让我得到了所有“项目”,包括“数据”下的那些,我不想要那些。


如果我在我的 XML 上执行以下操作,我会看到显示的元素名称:

XElement element = XElement.Parse(data);
foreach (XElement node in element.Elements())

  MessageBox.Show(node.Name.LocalName);

但是,当我这样做时,我根本看不到项目下的节点名称 - 我检查了 XElement,它确实有节点,当我输出它上面的名称时,“项目”连同信息和 ID 一起显示!

foreach (XElement node in element.Elements("items"))

  MessageBox.Show(node.Name.LocalName);

【问题讨论】:

我想通了 - 有一个额外的命名空间声明是空白的 - 向我的 XML 添加一个隐含的命名空间,为此使用 XNamespace 并将其添加到元素名称中解决了问题! 【参考方案1】:

假设 element 是您的 &lt;a:entry&gt; 元素:

var ids = element.Element("items")
                 .Elements("item")
                 .Select(item => item.Element("id").Value);

ElementElements 方法只返回直接子元素,而不是所有后代,因此它不返回 &lt;data&gt; 下的 &lt;items&gt; 元素

【讨论】:

这不起作用,虽然我认为它会因为这是我以前使用过的那种 thijng - 我发现我根本无法从根中获取任何元素有一个值节点关闭我在示例中留下的根,我也无法阅读它 - 如果我查询后代,那里有一些 - 只是不知道发生了什么。 一旦我像我自己的答案一样考虑命名空间,这确实有效! 您没有在问题中提供该信息...我尝试使用 &lt;a:entry&gt; 元素作为根,它工作正常。 我没有注意到 - 直到现在我也认为这是问题所在,我已经缩短了命名空间但没有注意到其中一个是空白的 - 所以一旦我把它带入你的答案就很好帐户,并发布了我使用的版本 - 根据您的回答,它有效,所以再次感谢它确实有帮助!【参考方案2】:

我的 XML 中有一个空白的命名空间声明,一旦我将它添加到我的代码中,我就没有注意到它起作用了 - 忘记了 LINQ 是非常面向命名空间的!

XNamespace ns = "http://example.org/namespace";
var ids = element.Element(ns + "items") 
                 .Elements("item") 
                 .Select(item => item.Element("id").Value); 

【讨论】:

非常有帮助 - 浪费了 2 小时。小记:XNamespace 而不是 XNameSpace 我已经根据反馈更正了这个答案的大小写,添加更正永远不会太迟,八年后前夕

以上是关于如何使用 LINQ 在 XML 中按名称获取元素的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 LINQ 选择特定元素名称?

在 XDocument 中按名称查询任意深度的元素

Linq to XML - 使用命名空间获取元素

LINQ to XML:如何在 C# 中获取元素值?

有没有更快的方法来检查 LINQ to XML 中的 XML 元素?

在 UIAutomation 中从 UIAElementArray 中按名称获取元素时遇到问题