为什么XPath位置选择表达式会返回多个节点?

6

在使用xpath时(我使用的时间不是很长),我发现了一些奇怪的东西。

XML的简化版本(完整的xml在这里,快照可在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>

表达式

//route[1]

我期望返回第一个route节点,结果是正确的。但是在尝试选择第一个message节点时,使用了

//message[1]

返回了多个message节点而不只是一个。

一开始我以为这是平台的问题,但在Android、桌面Java和几个在线xpath测试工具上进行测试后,我得到了相同的结果。

可能是什么问题呢?


1
非常好的基础问题。对于相同的问题,加一分。 - Arup Rakshit
可能是获取XPath结果集中第一个节点的重复问题。 - Jens Erat
1个回答

8
两个表达式分别表示其父级的第一个routemessage子元素。1 所有的route都是兄弟节点,共享单个body父元素,因此返回第一个route,仅此而已。然而,每个route包含其自己的一组message子元素,其中对于每个route节点,都将返回第一个message子元素。
如果您需要匹配整个XML文档中的第一个message元素,请使用:
(//message)[1]

括号告诉处理器找到与//message匹配的节点,然后选择器[1]会从这些节点中选择第一个。如果没有括号,选择器[1]将仅基于其父节点的子节点操作。

1 因为我是CSS选择器迷:您XPath表达式的选择器对应项分别是route:nth-of-type(1)message:nth-of-type(1)


我仍然感到困惑,尽管你是正确的。在 xpath 表达式中,例如 //message[1] 选择了第一个位置的 message 元素。但对我来说,这仍然是不明确的。 - Arup Rakshit
2
@Babai:关于“其父级别的第一个routemessage子元素”有什么不明确的地方? - BoltClock
我仍然知道//message会收集任何你能找到的message元素.. 对吗?如果是这样,那么父级关系是如何体现的呢?我不明白这一点...为什么没有父级时,paren就变成了story,而不是其他的东西呢..? :( - Arup Rakshit
2
@Babai:哦,那是因为括号改变了[1]谓词操作的轴。请参见http://www.w3.org/TR/xpath/#predicates和http://www.w3.org/TR/xpath/#node-sets。 - BoltClock
@BoltClock 但是不要删除那些CSS选择器,它们实际上帮助我相信这个故事而不是XPath... :) - Arup Rakshit
@BoltClock 非常感谢!!http://www.w3.org/TR/xpath/#node-sets 很有帮助.. - Arup Rakshit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接