Reputation: 21486
I want to limit the number of matches, or better yet, choose which indexed match, is made at a location step in XPath.
I know that if I have the following document:
<blah>
<foo>
<bar>
<target>one</target>
<target>two</target>
</bar>
<bar>
<target>three</target>
<target>four</target>
</bar>
</foo>
</blah>
I can limit the expression to only include the first <bar>
directly under <foo>
like the following, in order to only return <target>one</target>
and <target>two</target>
:
//foo/bar[1]/target
But now what if I have this:
<blah>
<foo>
<blah>
<bar>
<target>one</target>
<target>two</target>
</bar>
</blah>
<blah>
<bar>
<target>three</target>
<target>four</target>
</bar>
</blah>
</foo>
</blah>
I still only want the expression to yield <target>one</target>
and <target>two</target>
. But the following doesn't work; it will actually match <bar>
under each <foo><blah>
//foo//bar[1]/target
Apparently there is a subtle distinction: bar[1]
means "the first child of some element", not "the first element that matches this location step in the path expression".
How can I limit the expression (without naming the <blah>
elements, because they can vary) so that when it reaches the //foo//bar
location it only retains the first match of <bar>
before it continues matching the expression?
Upvotes: 1
Views: 64
Reputation: 21486
Ah, with just a few more seconds of thought I found the answer! (Actually forming the question helped me discover the solution.)
The secret is simply to use parentheses:
(//foo//bar)[1]/target
If I'm understanding it correctly, the expression //foo//bar[1]
says, "for every … <bar>
you match, only take the first one of them for the parent", so if there are multiple "first-bars", it will take each of the "first-bars".
Instead the expression (//foo//bar)[1]
says "once you match … <bar>
, only take the first matching one; then evaluate the rest of the path from that one matching <bar>
.
Whew! I wish every road bump could be this simple to get past.
Upvotes: 1