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 ..

Share:
23,964
newman
Author by

newman

Updated on December 06, 2020

Comments

  • newman
    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
    newman over 13 years
    Thanks 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
    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
    Admin over 13 years
    and @miliu: the count test is not needed. Check @kevpie answer.
  • Dimitre Novatchev
    Dimitre Novatchev over 13 years
    You 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
    kevpie over 13 years
    @Dimitre Thanks for holding my hand. I am SO n00b.
  • lajarre
    lajarre over 11 years
    what is the difference with @DimitreNovatchev 's //*[not(*)]?
  • Dimitre Novatchev
    Dimitre Novatchev over 11 years
    @lajarre, This is equivalent to the second expression in my answer -- only longer.
  • rrs
    rrs almost 10 years
    Can 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
    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
    rrs almost 10 years
    I understand what it does, but not how it does it. Why/how does not(*) select leaf nodes/elements?
  • Dimitre Novatchev
    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
    rrs almost 10 years
    Thank you, I'll check it out.