如何将 XPath 与 XElement 或 LINQ 一起使用?

Posted

技术标签:

【中文标题】如何将 XPath 与 XElement 或 LINQ 一起使用?【英文标题】:How to use XPath with XElement or LINQ? 【发布时间】:2010-09-04 15:19:33 【问题描述】:

考虑以下 XML:

<response>
  <status_code>200</status_code>
  <status_txt>OK</status_txt>
  <data>
    <url>http://bit.ly/b47LVi</url>
    <hash>b47LVi</hash>
    <global_hash>9EJa3m</global_hash>
    <long_url>http://www.tumblr.com/docs/en/api#api_write</long_url>
    <new_hash>0</new_hash>
  </data>
</response>

我正在寻找一种非常短的方法来获取 &lt;hash&gt; 元素的值。我试过了:

var hash = xml.Element("hash").Value;

但这不起作用。是否可以向XElement 提供 XPath 查询?我可以使用较旧的 System.Xml 框架来做到这一点,例如:

xml.Node("/response/data/hash").Value

在 LINQ 命名空间中有类似的东西吗?


更新:

在胡思乱想之后,我找到了一种方法来做我想做的事情:

var hash = xml.Descendants("hash").FirstOrDefault().Value;

我仍然有兴趣看看是否有人有更好的解决方案?

【问题讨论】:

在这种情况下不要使用 FirstOfDefault(),因为如果没有找到“hash”,你会得到一个 NullReferenceException。改用 First(),你会得到一个更具描述性的异常。 如果您希望“哈希”始终存在,请使用 First()。否则,只要在访问 Value 属性之前检查 null,FirstOrDefault() 就可以了。 【参考方案1】:

要将 XPath 与 LINQ to XML 结合使用,请添加 System.Xml.XPath 的 using 声明,这会将 System.Xml.XPath.Extensions 的扩展方法纳入范围。

在你的例子中:

var value = (string)xml.XPathEvaluate("/response/data/hash");

【讨论】:

好的,似乎最接近原始问题 其实(现在?)在System.Xml.XPath @DanFriedman 它没有移动。注意链接是类文档,稍早我给出了命名空间(没有链接)。 另请注意,您需要通过 NuGet 为 UWP 应用添加程序集:link 我发现使用方法 XPathSelectElement 并取回 XElement 而不是对象更容易。【参考方案2】:

其他人已经完全合理地建议如何使用“本机”LINQ to XML 查询来做你想做的事。

但是,为了提供许多替代方案,请考虑使用XPathSelectElementXPathSelectElementsXPathEvaluate 来根据XNode 评估XPath 表达式(它们都是XNode 上的扩展方法)。您还可以使用CreateNavigatorXNode 创建一个XPathNavigator

我个人非常喜欢直接使用 LINQ to XML API,因为我是 LINQ 的忠实粉丝,但如果您更熟悉 XPath,以上内容可能会对您有所帮助。

【讨论】:

【参考方案3】:

看,在处理 LINQ to XML 时,为什么不使用 LINQ 来获取实际对象。

后代从整个 XML 中查找每个元素并列出与指定名称匹配的所有对象。因此,在您的情况下,哈希是它找到的名称。

所以,与其做

var hash = xml.Descendants("hash").FirstOrDefault().Value;

我会像这样分开:

var elements = xml.Descendants("hash");
var hash = elements.FirstOrDefault();

if(hash != null)
 hash.Value // as hash can be null when default. 

通过这种方式,您还可以获取属性、节点元素等。

查看这篇文章以清楚地了解它,以便它有所帮助。 http://www.codeproject.com/KB/linq/LINQtoXML.aspx 我希望这能帮到您。

【讨论】:

@adhishek +1 用于解释将元素与其自己的变量分离的价值,以便您可以执行其他操作,例如获取属性等。 使用 XPath 的一个原因是您失去了 XPath 可以做而 Linq 不能做的所有事情。首先想到的是执行一个在运行时定义的查询(比如从配置中读取的表达式或其他)。【参考方案4】:

您可以使用 .Element() 方法链接元素以形成类似 XPath 的结构。

你的例子:

XElement xml = XElement.Parse(@"...your xml...");
XElement hash = xml.Element("data").Element("hash");

【讨论】:

我认为这是最好的答案,因为它可以在继续使用 LINQ to XML(推荐)而不是使用 XPath 和 LINQ to XML 查询(不推荐)的同时完成工作。跨度> 使用 XPath 更加简洁,特别是如果您正在寻找任何大孩子或其他孩子。 Element() 可以返回 null,所以这是不安全的。【参考方案5】:

我试图想出一个 LINQesq 框架来生成 xpath。 它允许您使用 c# lambda 表达式描述 xpath

var xpath = CreateXpath.Where(e => e.TargetElementName == "td" && e.Parent.Name == "tr");

var xpath = CreateXpath.Where(e => e.TargetElementName == "td").Select(e => e.Text);

不确定这在这种情况下是否有帮助,但您可以在此处找到文档:

http://www.syntaxsuccess.com/viewarticle/how-to-create-xpath-using-linq

【讨论】:

以上是关于如何将 XPath 与 XElement 或 LINQ 一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

子 XElement 的索引

如何将 Dictionary<XElement,XElement> 转换为 xml 文件?

如何获取 XML 或 XElement 变量中的特定元素计数

如何将 XElement 转换为 XDocument

如何将带有 xml 后代的 XElement 导入 SQL Server

如何在这里使用 XPath contains()?