在XPath中选择第一个结果

时间:2009-05-21 11:39:28

标签: xpath

我看过这个问题:Select first instance only with 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>

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

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

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

带回两个节点的结果集。我以为我可以使用last()获得最深的一个,所以我最后加了解,但没有用。

5 个答案:

答案 0 :(得分:11)

确保last()的范围正确。尝试:

(/container/container/ancestor-or-self::container/data[@id="1"])[last()]

类似地:

//container[last()]

(//container)[last()]

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

答案 1 :(得分:6)

你是如何尝试使用last()的?我认为这应该有效:

/container/container/ancestor-or-self::container/data[@id="1"][last()]

编辑:

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

(/container/container/ancestor-or-self::container/data[@id="1"])[last()]

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

<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>

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

(/container/container/ancestor-or-self::container[data[@id="1"]])[last()]/data[@id="1"]

顺便说一句,如果有多个@ id-is-1&lt; data&gt;一个容器的孩子,这将返回所有这些。仅返回第一个这样的&lt; data&gt;元素:

(/container/container/ancestor-or-self::container[data[@id="1"]])[last()]/data[@id="1"][1]

答案 2 :(得分:1)

我不是100%清楚你要求的是什么,但如果我读得对,也许你只是想:

/container/container/ancestor-or-self::container[1]/data[@id='1']

注意“[1]”

编辑:考虑一下这一点,以下对我来说对所有案例都适用于@ id = $ N

/container/container/ancestor-or-self::container[data[@id=$N]][1]/data[@id=$N]

非常极端xpathing就在那里。基本上发生的事情是来自祖先或自我的节点集返回位置1的最低顺序 - 这是你想要的那个 - 但你需要在其上放置第二个条件,该节点也有你感兴趣的数据节点,一旦满足这些条件,您就拥有了正确的节点,现在您只想进一步挖掘实际数据。

如果你将它分开并将其视为一种算法,99%的时间会变得更容易:)

答案 3 :(得分:0)

而不是

@id="1"

你试过了吗?

position() == 1

答案 4 :(得分:0)

试 [位置()= 1]

离。

  

/容器/容器/祖先或自::容器/数据[位置()= 1]