If I have an XPathNavigator positioned on a node, how can I get an XPath expression that represents the path to that node, from the root?
For example, if the XML is:
<data>
<class name='dogs'>
<item name='doberman />
<item name='husky' />
</class>
<class name='cats'>
<item name='persian' />
<item name='tabby' />
</class> </data>
</data>
…then the path to the persian cat could be expressed as /data/class[2]/item[1]
I can enumerate the ancestors of the node in question with SelectAncestors() (or I could iteratively climb up the parent relationship with SelectParent()), but that doesn’t get me the positional information.
Would I have to evaluate an XPath using position() for each ancestor, or is there a better way to do this?
Assuming you’re interested only in the xpath of xml elements, I implemented a brute force algorithm (i.e. traversing the XML structure) as extension methods on
XmlElement. This is very similar to @Zenexer’s answer, although I had already started on my own version when he posted his.Also, intrigued by Alexei’s tip about performance, I created a sort of test case using a somewhat complex XML file lyring around here. Then I implemented two versions of the same algorithm; one that depends on PreviousSibling, and other that iterates nodes sequentially. A third version relied on XPath’s
position()function, but it didn’t work as expected and was discarded.While you should check for yourself, in my machine the results showed a significant performance advantage for the iterative version — 1.7s against 21s scored by the siblings version.
Importart: these extension methods are declared inside a
static class XmlElementExtension.PreviousSibling version
Iterative version
The test case