A--C
A--C

Reputation: 36449

Why would an xpath position selection expression return multiple nodes?

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 &amp; Revere Ave" />
</routeConfiguredForMessage>
      <text>Stop moved&#10;across Revere&#10;During&#10;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 &amp; Revere Ave" />
</routeConfiguredForMessage>
      <text>Stop moved&#10;across Revere&#10;During&#10;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

Answers (1)

BoltClock
BoltClock

Reputation: 723378

Both expressions represent the first route and message child of its parent, respectively.1 All of your routes 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

Related Questions