Jens Bannmann
Jens Bannmann

Reputation: 5105

Find element which has specific child element, but no text nodes

For an XSLT template, I need an XPath expression targeting elements which have a specific child element, but no text nodes.

<!-- 1: matches -->
<a><b/></a>

<!-- 2: does not match -->
<a>foo bar quux<b/></a>

<!-- 3: does not match -->
<a>whatever <b/> further text</a>

<!-- 4: does not match -->
<a>whatever <b/> further text <b/></a>

 <!-- 5: does not match -->
<a><x/><b/></a>

<!-- 6: does not match -->
<a>foo bar quux</a>

I came up with a[*[1 = last() and name() = 'b']], but then case 2 or 3 are matched when they should not. The reason, of course, is that the * selects elements and does not care about text nodes. So how do I do this instead?

Upvotes: 5

Views: 645

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243509

a[b and not(text() or *[2])]

This selects every a child of the current node (context node) that has a b child, and doesn't have any text node children or a second element child.

If you also don't want to have any PI or comment children, you can use a shorter version:

a[b and not(node()[2])]

Upvotes: 2

Woody
Woody

Reputation: 5130

You could just use

a[count(*)=1 and b and not(text())]

If you are only looking for one b, no other elements and no text. Bear in mind that if you have a carriage return in your xml, some processors will take that as text.

Upvotes: 3

Related Questions