如何在XElement或LINQ中使用XPath?


77

考虑以下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>

我正在寻找一种获取<hash>元素值的非常短的方法。我试过了:

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

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

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

LINQ名称空间中是否有类似的东西?


更新:

经过进一步研究之后,我找到了一种方法来做我想做的事情:

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

我还是想看看是否有人有更好的解决方案?


3
在这种情况下,请勿使用FirstOfDefault(),因为如果找不到“ hash”,则会得到NullReferenceException。使用First()代替,您将获得更具描述性的异常。
kaalus 2012年

3
如果您希望“哈希”始终存在,请使用First()。否则,只要访问Value属性之前检查是否为null,FirstOrDefault()就可以。
安富

Answers:


137

要将XPath与LINQ to XML一起使用,请为添加一个using声明System.Xml.XPath,这会将的扩展方法System.Xml.XPath.Extensions引入范围。

在您的示例中:

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

1
好吧,似乎最接近原始问题了
Henk Holterman 2010年

3
实际上,它在(现在?)中System.Xml.XPath
丹·弗里德曼

@DanFriedman它没有动。注意链接是指向类文档的,稍早我给出了命名空间(没有链接)。
理查德

另请注意,您需要通过NuGet为UWP应用添加程序集:链接
Matt__C

1
我发现使用方法XPathSelectElement并返回XElement而不是对象更容易。
user3042674 '18

38

其他人则完全合理地建议了如何对XML查询使用“本机” LINQ来完成所需的工作。

然而,在提供大量替代的利益,考虑XPathSelectElementXPathSelectElementsXPathEvaluate评估对一个XPath表达式XNode(他们所有的扩展方法XNode)。您还可以使用CreateNavigator为创建XPathNavigator一个XNode

就个人而言,我是直接使用LINQ to XML API的忠实拥护者,因为我是LINQ忠实拥护者,但是如果您对XPath更满意,那么以上内容可能会对您有所帮助。


14

请参阅,在处理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 希望对您有所帮助。


2
@adhishek +1解释元件分离到它的价值是自己的变量,所以你可以做其他的东西,以获得更多的属性,等等。
保罗·弗赖尔

1
使用XPath的原因之一是您失去了XPath可以做的所有事情,而Linq却做不到。首先想到的一个明显的问题是执行一个在运行时定义的查询(例如,从配置中读取的表达式等)。
Marco Mp

8

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

例如:

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

1
我认为这是最好的答案,因为在继续使用LINQ to XML(推荐)而不是将XPath与LINQ to XML查询一起使用(不推荐)的同时,它可以完成工作。
Girish Jain

2
使用XPath更简洁,特别是在您正在寻找大孩子或其他大孩子的情况下。
安富

Element()可以返回null,因此这是不安全的。
西蒙·摩根

2

我试图提出一个用于生成xpath的LINQesq框架。它使您可以使用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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.