选择XPath中的第一个结果
我已经看了这个问题: 但如果我有这样一个节点集:选择XPath中的第一个结果,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 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的“数据”节点,它应该首先来自最低的节点或最近的祖先。因此,如果我在“current”(/container/container)上找不到它,我应该查看祖先并得到最近的一个(或者最终什么也找不到)。我试过这个:
/容器/容器/祖先或self::容器/数据[@id=“1”]
这将返回一个包含两个节点的结果集。我想我可以用last()来得到最深的一个,所以我把它钉在了最后,但没有用。我不是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]
非常极端的体验。基本上,发生的是来自祖先或自我的节点集返回位置1处的最低顺序-这是您想要的-但您需要对其设置第二个条件,即节点也有您感兴趣的数据节点,一旦满足了这些条件,就有了正确的节点,现在您只需要进一步深入实际数据
如果将xpath分解并将其视为一种算法,99%的情况下xpath会变得更容易:)您是如何尝试将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>
顺便说一下,如果一个容器中有多个@id-is-1子容器,这将返回所有子容器。要仅返回第一个此类元素,请执行以下操作:
而不是
@id="1"
您是否尝试过:
position() == 1
确保last()
的范围正确。尝试:
(/container/container/ancestor-or-self::container/data[@id="1"])[last()]
同样地:
//container[last()]
以及:
它们不是一回事。第一个将返回层次结构每个级别的最后一个容器节点(多个匹配项),第二个将返回找到的最后一个容器节点(一个匹配项)。try
[位置()=1]
前
/容器/容器/祖先或self::容器/数据[position()=1]
如果我在这里对所需结果的理解是正确的(大If),那么这将不起作用,因为最后一个()将在祖先或自我的两个分支上匹配-这是真正的问题,所以您需要提前(如我所做)或延迟(如Dave所做)剪裁结果集。这一个做到了。非常感谢(大家也一样)!该规范可以更加清晰。您想要数据节点吗?数据节点的id必须为1?形成原始容器如果数据节点的id不为1,则要将文档向上移动到父容器,以查看该容器是否具有id为1的数据节点,如果不继续,则直到找到id为1的数据节点为止。这说明了吗?我试图把我想要的描述得更清楚一点,尽管有些人猜到了。很抱歉如果position()==1可以工作,那么就一起删除祖先或self::all。我认为要求不只是任何第一个数据节点,而是id为1的数据节点。问题并没有那么清楚。事实上,我发现如果在匹配数据元素之前指定了子容器节点,则这种方法不起作用。@Nick Spacek-我改进了下面的答案,现在它甚至涵盖了那个角落的情况。我尝试过这样做,但并不涵盖所有情况。如果我在寻找@id='2',该怎么办?我希望在祖先之前支持当前节点的结果,但能够回退。
(/container/container/ancestor-or-self::container/data[@id="1"])[last()]
//container[last()]
(//container)[last()]