1
<div>
<p> text 1 </p> 
<p>
    <a href="http://www.google.com">text 2</a>
</p> 
<p> text 3  </p> 
<p> text 4 </p> 
</div>

I used this: //p but this also gives me the <p> where text 2 is. I want <p>s without children. I need: text 1, text 3, text 4

kjhughes
  • 106,133
  • 27
  • 181
  • 240
cosmos7263
  • 13
  • 2

1 Answers1

2

Here are XPaths for various interpretations of no children...

  • No element children:

    //p[not(*)]
    
  • No text children:

    //p[not(text())]
    
  • No children of any type:

    //p[not(node())]
    

Replace p above with any other element name, or * to target elements regardless of name.

kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • To add a extra alternative, you could also use //p[text()[normalize-space()]], to accomplish the wanted result – Siebe Jongebloed Oct 22 '22 at 10:25
  • @SiebeJongebloed: Yes, while `//p[not(*)` selects for the *absence* of element children (one interpretation of the requested "no children"), your XPath selects for the *presence* of (non-whitespace-only) text-node children. As such, `//p[not(*)]` would exclude `p` elements with [*mixed content*](https://stackoverflow.com/q/66148477/290085) whereas your XPath would also include `p` elements with mixed content. – kjhughes Oct 22 '22 at 12:53