Reputation: 36449
While working with xpath (which hasn't been very long), I came across something odd.
Shortened version of the xml (The full xml is here and a snapshot is available on pastebin):
<?xml version="1.0" encoding="utf-8" ?>
<body copyright="All data copyright San Francisco Muni 2013.">
<route tag="all">
<message id="10268" creator="jflynn" startBoundary="1378121400000" startBoundaryStr="Mon, Sep 02 04:30:00 PDT 2013" endBoundary="1378191540000" endBoundaryStr="Mon, Sep 02 23:59:00 PDT 2013" sendToBuses="false">
<text>Sunday schedules today.</text>
</message>
</route>
<route tag="44">
<message id="10221" creator="mlee" startBoundary="1377525600000" startBoundaryStr="Mon, Aug 26 07:00:00 PDT 2013" endBoundary="1382857140000" endBoundaryStr="Sat, Oct 26 23:59:00 PDT 2013" sendToBuses="false">
<routeConfiguredForMessage tag="44"> <stop tag="6420" title="Silver Ave & Revere Ave" />
</routeConfiguredForMessage>
<text>Stop moved across Revere During Construction</text>
</message>
<message id="10222" creator="mlee" startBoundary="1377525600000" startBoundaryStr="Mon, Aug 26 07:00:00 PDT 2013" endBoundary="1382857140000" endBoundaryStr="Sat, Oct 26 23:59:00 PDT 2013" sendToBuses="false">
<routeConfiguredForMessage tag="44"> <stop tag="6420" title="Silver Ave & Revere Ave" />
</routeConfiguredForMessage>
<text>Stop moved across Revere During Construction</text>
</message>
</route>
</body>
The expression
//route[1]
returned the first route
node like I expected. However, when attempting to select the first message
node, with
//message[1]
multiple message
nodes were returned rather than just one.
At first I assumed that it was a platform problem, but testing on Android, Desktop Java and a couple of online xpath testers, I'm getting the same results.
What could be the problem?
Upvotes: 6
Views: 4233
Reputation: 723378
Both expressions represent the first route
and message
child of its parent, respectively.1 All of your route
s are siblings sharing a single body
parent, so the first of these is returned and only that. However each route
contains its own set of message
children, the first of which is being returned for every route
node.
If you need to match the first message
element in your entire XML document, use:
(//message)[1]
The parentheses tells the processor to find nodes matching //message
, then the [1]
predicate that comes after picks the first out of those nodes. Without them the [1]
predicate will simply operate based on children of their parent node.
1 Because I'm a CSS selector junkie: the selector counterparts for your XPath expressions are route:nth-of-type(1)
and message:nth-of-type(1)
, respectively.
Upvotes: 8