如何使用Xpath选择这些元素?

4

我有一份文档,类似于这样:

<root>
   <A node="1"/>
   <B node="2"/>
   <A node="3"/>
   <A node="4"/>
   <B node="5"/>
   <B node="6"/>
   <A node="7"/>
   <A node="8"/>
   <B node="9"/>
</root>

使用xpath,如何选择紧随给定A元素的所有连续B元素?
类似于following-silbing :: B,但我只希望它们是紧接着的元素。
如果我在A上(node == 1),那么我想选择节点2。 如果我在A上(node == 3),那么我不想选择任何内容。 如果我在A上(node == 4),那么我想选择5和6。
我可以在xpath中这样做吗? 编辑:它在XSL样式表select语句中。
编辑2:我不想使用各种元素上的节点属性作为唯一标识符。 我包括节点属性仅用于说明我的观点。 在实际的XML文档中,我没有用作唯一标识符的属性。 xpath“following-sibling :: UL [preceding-sibling :: LI [1] / @ node = current()/ @ node]”键入节点属性,这不是我想要的。
3个回答

5

简短回答(假设 current() 没有问题,因为此标签已标记为 XSLT):

following-sibling::B[preceding-sibling::A[1]/@node = current()/@node]

示例样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml"/>
    <xsl:template match="/">
        <xsl:apply-templates select="/root/A"/>
    </xsl:template>

    <xsl:template match="A">
        <div>A: <xsl:value-of select="@node"/></div>
        <xsl:apply-templates select="following-sibling::B[preceding-sibling::A[1]/@node = current()/@node]"/>
    </xsl:template>

    <xsl:template match="B">
        <div>B: <xsl:value-of select="@node"/></div>
    </xsl:template>
</xsl:stylesheet>

祝你好运!


提醒我使用 current() 来定位相对逻辑语句真是太有帮助了。 - Michael Shopsin

3

虽然@Chris Nielsen的回答是正确的方法,但在比较的属性不唯一的情况下会存在不确定性。更正确的解决方法是:

following-sibling::B[
  generate-id(preceding-sibling::A[1]) = generate-id(current())
]

这可以确保preceding-sibling::A与当前的A完全相同的,而不仅仅是比较一些属性值。除非您有保证唯一性的属性,否则这是唯一安全的方法。


+1;我本来想说的是following-sibling :: B [count(preceding-sibling :: A [1] | current()) = 1],但你的方法似乎更易懂。 - Chris Nielsen
在我看来,使用 count(...) 方法来确定节点标识语义上不如使用 generate-id() 方法,但有时我也会使用它。这有点取决于上下文,但总的来说,我更喜欢使用 generate-id() 方法,因为它更加明确。 - Tomalak

1
一个解决方案可能是首先使用following-sibling :: *收集所有以下节点,获取这些节点中的第一个并要求它是一个“B”节点。
following-sibling::*[position()=1][name()='B']

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