Consider this XML document:
<foo>
<bar id="aaa"/>
<jam>
<bar id="bbb"/>
</jam>
</foo>
I am trying to find the first <bar> element in the document.
Here's what I've discovered:
| Test# | XPath Expression | Evaluation Expression | Result |
|---|---|---|---|
| 1 | //bar |
@id |
aaa, bbb |
| 2 | //bar[1] |
@id |
aaa, bbb |
| 3 | (//bar)[1] |
@id |
aaa |
What I don't understand is why Test #2 returns aaa, bbb instead of just aaa. It's as if the [1] operator is not working.
My understanding was that in Test #2, the //bar expression would find both nodes, and then the [1] operator would choose the first one. Obviously, I'm missing something.
This seems to be confirmed by Test #3 which is apparently how to express what I really want.
Also, if you change the XML document to this:
<foo>
<bar id="aaa"/>
<bar id="bbb"/>
</foo>
then you get what I was expecting to see:
| Test# | XPath Expression | Evaluation Expression | Result |
|---|---|---|---|
| 1 | //bar |
@id |
aaa, bbb |
| 2 | //bar[1] |
@id |
aaa |
| 3 | (//bar)[1] |
@id |
aaa |
What subtlety am I missing here about how [1] is supposed to work?
The XPath specification contains this note regarding the // abbreviated syntax:
Note:
The path expression//para[1] does not mean the same as the path expression/descendant::para[1]. The latter selects the first descendantparaelement; the former selects all descendantparaelements that are the firstparachildren of their respective parents.
IOW, if you want to select the first bar element in the document you need to use:
/descendant::bar[1]
instead of:
//bar[1]
Unlike the other answers, I am not claiming it makes sense.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With