How to select all leaf nodes using XPath expression?
23,964
Solution 1
Use:
//node()[not(node())]
In case only element leaf nodes are wanted (and this needs clarification -- are elements that have non-element children considered leaf nodes?), then the following XPath expression selects them:
//*[not(*)]
Both expressions above are probably the shortest that select the desired nodes (either any-node or element -- leaf nodes).
Solution 2
Any elements with no element child
//*[not(child::*)]
Solution 3
Why less or equal to 1 ?
xmlNode.SelectNodes("//*[count(child::*) = 0]")
Make tests etc at this site http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm
Pretty helpful ..
Author by
newman
Updated on December 06, 2020Comments
-
newman over 3 years
I believe it's possible but couldn't figure out the syntax. Something like this:
xmlNode.SelectNodes("//*[count(child::*) <= 1]")
but this is not correct.
-
newman over 13 yearsThanks very much. This works great. So, it's more VB style equal. I thought it should be c-style because functions are case-sensitive. Why <= 1? I was confused by ChildNodes.Count which return 1 for <A>x</A>, but returns 0 for <A/>.
-
Admin over 13 years+1 Right answer. But it means: any elements with no element child. So, it will select elements with text node child, empty elements, elements with mixed content (text nodes, PI, comments)
-
Admin over 13 yearsand @miliu: the count test is not needed. Check @kevpie answer.
-
Dimitre Novatchev over 13 yearsYou probably meant: "Elements that don't have element-children" -- not "Elements with no children". It would be good to acknowledge this and to correct the text of your otherwise good answer.
-
kevpie over 13 years@Dimitre Thanks for holding my hand. I am SO n00b.
-
lajarre over 11 yearswhat is the difference with @DimitreNovatchev 's
//*[not(*)]
? -
Dimitre Novatchev over 11 years@lajarre, This is equivalent to the second expression in my answer -- only longer.
-
rrs almost 10 yearsCan you explain why this works? I've looked over the XPath syntax and some tutorials, but I can't quite understand why this works.
-
Dimitre Novatchev almost 10 years@rrs: The first expression selects any node in the XML document that doesn't have any children -- this is what a leaf node is -- by definition. The second does something similar, but it selects any element that doesn't have a child - element.
-
rrs almost 10 yearsI understand what it does, but not how it does it. Why/how does
not(*)
select leaf nodes/elements? -
Dimitre Novatchev almost 10 years
not(*)
means "does not have any element child" as "* selects all element children of the context node" as per the W3C XPath 1.0 recommendation: w3.org/TR/xpath/#path-abbrev (second bullet). This is a very short explanation, to go in depth, one needs a more or less full course in XPath. May I shamelessly recommend the second module of my Pluralsight training course on "XSLT 2.0 and 1.0 foundations"? The title of this course is "A Crash Course in XPath" and it is 70 minutes long: pluralsight.com/training/Courses/TableOfContents/… -
rrs almost 10 yearsThank you, I'll check it out.