我看过这个问题: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()获得最深的一个,所以我最后加了解,但没有用。
答案 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]