XElement或XDocument上的XPathEvaluate之间的区别?

时间:2012-11-26 11:38:05

标签: c# linq-to-xml xelement

在C#程序的某个地方,我需要从xml结构中获取属性值。我可以直接作为XElement到达这个xml结构,并有一个简单的xpath字符串来获取属性。但是,使用XPathEvaluate,我大部分时间都得到一个空数组。 (是的,有时,返回属性,但大多数情况下不是......对于完全相同的XElement和xpath字符串......) 但是,如果我首先将xml转换为字符串并将其重新分析为XDocument,我总是会返回该属性。有人可以解释这种行为吗? (我使用的是.NET 3.5)

主要返回空IEnumerable的代码:

string xpath = "/exampleRoot/exampleSection[@name='test']/@value";
XElement myXelement = RetrieveXElement();
((IEnumerable)myXElement.XPathEvaluate(xpath)).Cast<XAttribute>().FirstOrDefault().Value;

始终有效的代码(我得到我的属性值):

string xpath = "/exampleRoot/exampleSection[@name='test']/@value";
string myXml = RetrieveXElement().ToString();
XDocument xdoc = XDocument.Parse(myXml);
((IEnumerable)xdoc.XPathEvaluate(xpath)).Cast<XAttribute>().FirstOrDefault().Value;

使用测试xml:

<exampleRoot>
    <exampleSection name="test" value="2" />
    <exampleSection name="test2" value="2" />
</exampleRoot>

通过与周围根相关的建议,我在测试程序中进行了一些“干测试”,使用相同的xml结构(txtbxXml和txtbxXpath代表上面描述的xml和xpath表达式):

// 1. XDocument Trial:
((IEnumerable)XDocument.Parse(txtbxXml.Text).XPathEvaluate(txtbxXPath.Text)).Cast<XAttribute>().FirstOrDefault().Value.ToString();
// 2. XElement trial:
((IEnumerable)XElement.Parse(txtbxXml.Text).XPathEvaluate(txtbxXPath.Text)).Cast<XAttribute>().FirstOrDefault().Value.ToString();
// 3. XElement originating from other root:
((IEnumerable)(new XElement("otherRoot", XElement.Parse(txtbxXml.Text)).Element("exampleRoot")).XPathEvaluate(txtbxXPath.Text)).Cast<XAttribute>().FirstOrDefault().Value.ToString();

结果:案例1和3生成正确的结果,而案例2抛出nullref异常。 如果案例3失败并且案例2成功,那对我来说会有所帮助,但现在我没有得到它......

1 个答案:

答案 0 :(得分:8)

问题是XPath表达式是从指定节点的子节点开始的。如果以XDocument开头,则根元素是子节点。如果您从代表XElement节点的exampleRoot开始,则子节点是两个exampleSection节点。

如果将XPath表达式更改为"/exampleSection[@name='test']/@value",它将从元素开始工作。如果您将其更改为"//exampleSection[@name='test']/@value",则可以同时使用XElementXDocument