简体   繁体   English

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

[英]Difference between XPathEvaluate on XElement or XDocument?

Somewhere in a C# program, I need to get an attribute value from an xml structure. 在C#程序的某个地方,我需要从xml结构中获取属性值。 I can reach this xml structure directly as an XElement and have a simple xpath string to get the attribute. 我可以直接作为XElement到达这个xml结构,并有一个简单的xpath字符串来获取属性。 However, using XPathEvaluate, I get an empty array most of the time. 但是,使用XPathEvaluate,我大部分时间都得到一个空数组。 (Yes, sometimes, the attribute is returned, but mostly it isn't... for the exact same XElement and xpath string...) However, if I first convert the xml to string and reparse it as an XDocument, I do always get the attribute back. (是的,有时,返回属性,但大多数情况下不是......对于完全相同的XElement和xpath字符串...)但是,如果我先将xml转换为字符串并将其重新解析为XDocument,我会总是得到属性。 Can somebody explain this behavior ? 有人可以解释这种行为吗? (Am using .NET 3.5) (我使用的是.NET 3.5)

Code that mostly returns an empty IEnumerable: 主要返回空IEnumerable的代码:

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

Code that does always work (I get my attribute 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;

With the test xml: 使用测试xml:

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

By suggestion related to a surrounding root, I did some 'dry tests' in a test program, using the same xml structure (txtbxXml and txtbxXpath representing the xml and xpath expression described above): 通过与周围根相关的建议,我在测试程序中进行了一些“干测试”,使用相同的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();

Result : case 1 and 3 produce the correct result, while case 2 throws a nullref exception. 结果:案例1和3生成正确的结果,而案例2抛出nullref异常。 If case 3 would fail and case 2 succeed, it would have made some sense to me, but now I don't get it... 如果案例3失败并且案例2成功,那对我来说会有一些意义,但现在我不明白......

The problem is that the XPath expression is starting with the children of the specified node. 问题是XPath表达式是从指定节点的子节点开始的。 If you start with an XDocument , the root element is the child node. 如果从XDocument开始,则根元素是子节点。 If you start with an XElement representing your exampleRoot node, then the children are the two exampleSection nodes. 如果以表示exampleRoot节点的XElement exampleRoot ,则子节点是两个exampleSection节点。

If you change your XPath expression to "/exampleSection[@name='test']/@value" , it will work from the element. 如果将XPath表达式更改为"/exampleSection[@name='test']/@value" ,它将从元素开始工作。 If you change it to "//exampleSection[@name='test']/@value" , it will work from both the XElement and the XDocument . 如果将其更改为"//exampleSection[@name='test']/@value" ,它将同时适用于XElementXDocument

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM