Difference between XPathEvaluate on XElement or XDocument?

杀马特。学长 韩版系。学妹 提交于 2021-02-07 20:40:50

问题


Somewhere in a C# program, I need to get an attribute value from an xml structure. I can reach this xml structure directly as an XElement and have a simple xpath string to get the attribute. However, using XPathEvaluate, I get an empty array most of the time. (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. Can somebody explain this behavior ? (Am using .NET 3.5)

Code that mostly returns an empty 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:

<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):

// 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. If case 3 would fail and case 2 succeed, it would have made some sense to me, but now I don't get it...


回答1:


The problem is that the XPath expression is starting with the children of the specified node. If you start with an XDocument, the root element is the child node. If you start with an XElement representing your exampleRoot node, then the children are the two exampleSection nodes.

If you change your XPath expression to "/exampleSection[@name='test']/@value", it will work from the element. If you change it to "//exampleSection[@name='test']/@value", it will work from both the XElement and the XDocument.



来源:https://stackoverflow.com/questions/13564072/difference-between-xpathevaluate-on-xelement-or-xdocument

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!