2010-09-04 50 views
69

考虑下面的XML:如何在XElement或LINQ中使用XPath?

<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; 

但是这不起作用。是否可以向XElement提供XPath查询?我可以与老System.Xml框架做了,做这样的事情:

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

有没有这样的事情在LINQ命名空间?


UPDATE:

与此胡闹周围多一些我找到了一种方法做我想要做后:

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

我还是很想看看任何人有更好的解决方案?

+3

不要使用FirstOfDefault()在这种情况下,因为如果没有找到“散列”,你会得到一个NullReferenceException。使用First()代替,你会得到一个更具描述性的例外。 – kaalus 2012-03-03 00:43:57

+2

如果您希望“散列”始终存在,请使用First()。否则,只要在访问Value属性之前检查null,FirstOrDefault()就没有问题。 – 2016-03-17 20:44:30

回答

120

要使用带有LINQ to XML的XPath,请为System.Xml.XPath添加使用声明,这将使扩展方法System.Xml.XPath.Extensions进入范围。

在您的例子:

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

好吧,似乎最接近原始问题 – 2010-09-04 19:21:03

+3

实际上,它是(现在在?)在'System.Xml.XPath'中。 – 2015-05-08 14:20:46

+0

@DanFriedman它没有移动。注意链接是类文档,稍早我给名称空间(没有链接)。 – Richard 2015-05-08 14:38:05

13

看到,随着LINQ处理到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用于解释将元素分离到它自己的变量的值,以便您可以执行其他操作,例如获取属性等。 – 2010-09-04 15:38:13

+1

使用XPath的一个原因是您丢失了XPath可以执行的所有这些操作,而Linq无法执行。想到的第一个明显的例子就是执行一个在运行时定义的查询语句(比如从配置文件中读取一个表达式或者其他)。 – 2013-05-23 16:36:36

33

其他人完全合理​​的建议如何使用“原生”的LINQ to XML查询你想要做什么。

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

我个人是直接用LINQ to XML API的忠实粉丝,因为我是一个大风扇LINQ,但如果你更舒适的使用XPath,上面可以帮助你。

5

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

对于示例:

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

我认为这是最好的答案,因为它可以继续使用LINQ to XML(推荐使用),而不是使用带有LINQ to XML查询的XPath(这不推荐)。 – 2015-10-01 17:55:23

+1

使用XPath更简洁,特别是如果您正在寻找任何大孩子或更高级别的孩子。 – 2016-03-17 20:48:43

1

我试图拿出生成XPath中LINQesq框架。 它可以让你使用C#拉姆达描述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