如何选择具有特定节点作为子节点的第一个前一个兄弟?

时间:2014-02-11 07:38:16

标签: xml xslt xpath xslt-1.0

我一直在尝试编写一个XPath语句,它将选择节点的第一个前一个兄弟。那个兄弟应该有一个特定的节点作为它的孩子。

例如:

<a>
    <c></c>
    ....
    <b></b>
</a>

<a></a>
....
....
<a></a>

<a>
   <b> start </b>
</a>

在上面的XML中,如果我的上下文位于其子a内有start文本的节点b。如何选择孩子为a的前一个节点b

我尝试了preceding-sibling::*[b][1],但如果a是其第一个孩子,则只选择节点b。我也尝试了preceding-sibling::*[1][b],但它只检查前面的第一个a节点,如果它不包含b,则测试失败。

注意:我正在使用XSLT 1.0

有人能建议我解决方案吗?

Thnx提前!!

3 个答案:

答案 0 :(得分:4)

喜欢这个。 (“第一个有<b>孩子的兄弟姐妹”

preceding-sibling::a[b][1]

或者这个(“前面的第一个兄弟姐妹,但只有它有一个<b>孩子”):

preceding-sibling::a[1][b]

多个谓词必须一个接一个地为真。因此,这个:

preceding-sibling::a[b and position() = 1]

相当于第二个表达式,但不是第一个表达式。

答案 1 :(得分:3)

我相信:

preceding-sibling::*[b][1]

或者最好:

preceding-sibling::a[b][1]

应该可以正常工作。

  

我尝试过previous-sibling :: * [b] [1],但它只选择节点a if b   是它的第一个孩子。

我认为不是这样。

答案 2 :(得分:1)

使用此输入:

<root>
    <a>
        <c></c>
        <b>SUCCESS</b>
    </a>
    <a>FAIL</a>
    <a>FAIL</a>
    <a>
        <b> start </b>
    </a>
</root>

和这个样式表

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="a[b[.=' start ']]">
        <xsl:copy>
        <xsl:value-of select="preceding-sibling::a[b]"/>
        </xsl:copy>

    </xsl:template>
</xsl:stylesheet>

输出

<root>
   <a>
      <c/>
      <b>SUCCESS</b>
   </a>
   <a>FAIL</a>
   <a>FAIL</a>
   <a>SUCCESS</a>
</root>