在XPath中选择第一个结果

Nic*_*cek 9 xpath

我看过这个问题:只用XPath选择第一个实例?

但如果我有这样的节点集:


<container value="">
  <data id="1"></data>
  <data id="2">test</data>
  <container>
    <data id="1">test</data>
    <data id="3">test</data>
  </container>
</container>
Run Code Online (Sandbox Code Playgroud)

现在我的场景是这个节点集在文档内部,我有一个指向内部容器的指针.所以我必须在XPath前加上"/ container/container"(路径实际上更长,但对于这个例子,这应该这样做).

编辑:我想要的是一个id为1的"数据"节点,它应该来自最低节点或最近的祖先.所以,如果我在"当前"(/容器/容器)上找不到它,我应该看看祖先并得到最近的一个(或者最后,找不到任何东西).我试过这个:

/容器/容器/祖先或自::容器/数据[@ ID = "1"]

这会带回两个节点的结果集.我以为我可以用last()来获得最深的那个,所以我最后加了解,但无济于事.

Dav*_*ebb 11

确保last()正确确定范围.尝试:

(/container/container/ancestor-or-self::container/data[@id="1"])[last()]
Run Code Online (Sandbox Code Playgroud)

同理:

//container[last()]
Run Code Online (Sandbox Code Playgroud)

和:

(//container)[last()]
Run Code Online (Sandbox Code Playgroud)

不是一回事.第一个将返回层次结构的每个级别的最后一个容器节点 - 多个匹配 - 第二个将返回找到的最后一个容器节点 - 一个匹配.


Dan*_*tin 6

你是怎么尝试追上last()的?我认为这应该有效:

/container/container/ancestor-or-self::container/data[@id="1"][last()]
Run Code Online (Sandbox Code Playgroud)

编辑:

是的,当然,我忘记了括号:

(/container/container/ancestor-or-self::container/data[@id="1"])[last()]
Run Code Online (Sandbox Code Playgroud)

这使其与其他答案相同; 然而,正如原始海报所指出的那样,这个表达失败了:

<container value="">
  <container>
    <data id="1">a3</data>
    <data id="3">a4</data>
  </container>
  <data id="1">a1</data>
  <data id="2">a2</data>
</container>
Run Code Online (Sandbox Code Playgroud)

根据stackoverflow的精神,我可以将我的答案与其他答案中的一个结合起来,并得到适用于所有情况的东西:

(/container/container/ancestor-or-self::container[data[@id="1"]])[last()]/data[@id="1"]
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果一个容器中有多个@ id-is-1 <data>子节点,则会返回所有这些子节点.要仅返回第一个这样的<data>元素:

(/container/container/ancestor-or-self::container[data[@id="1"]])[last()]/data[@id="1"][1]
Run Code Online (Sandbox Code Playgroud)