Difference between XPathEvaluate on XElement or XDocument?
c#, linq-to-xml, xelement
Solution
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`.
Problem
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...