XSLT,如何找到前一个兄弟的(包含文本)最后一个带有文本的子元素?

时间:2014-01-01 06:07:05

标签: xslt

在下面的XML和XSLT中,在xml中,元素“i”是当前位置,在那里我需要找到前一个兄弟的最后一个子文本。

Input1.xml

  <root>
    <aa>
    <a>
        <b>Text1</b>
        <c>Text2</c>
        <d>Text3
            <n>Text11
                <o>Text12
                    <p>Text13</p>
                </o>
            </n>
        </d>
    </a>
    <e>
        <f>
            <g>Text4</g>
        </f>
        <h>Text5
            <j>Text7</j>
            <k>Text8</k>
        </h>
    </e>
    <i>Text6</i>
    </aa>
  </root>

Child.xsl

  <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="i">
        <xsl:variable name="var0"><xsl:apply-templates select="preceding-sibling::*[1]"/></xsl:variable>
        <xsl:variable name="var1">
            <xsl:for-each select="var0">
                <xsl:value-of select="child::*[last()]"/>
            </xsl:for-each>
        </xsl:variable>

        <xsl:variable name="var2">
            <xsl:for-each select="$var1">
                <xsl:value-of select="child::*[last()]"/>
            </xsl:for-each>
        </xsl:variable>

            <ppp><xsl:copy-of select="."/><jj>-The last preceding child text is <xsl:value-of select="$var2"/>-</jj></ppp>
    </xsl:template>
  </xsl:stylesheet>

必需的输出是

  

Text6 最后一个子文本是 - Text8

2 个答案:

答案 0 :(得分:7)

看起来你的意思是前兄弟姐妹的最后一个后代非空白,而不是最后一个儿童文本。 (请记住,您在XML文件中向我们展示的压痕也是文本节点。)

获取前面的兄弟元素。获取其文本节点后代。从那些选择非空白的那些。从那些中选择最后一个。

应该是这样的:

select="preceding-sibling::*/descendant::text()[normalize-space()!=''][last()]"

(我正在利用先前兄弟的主要节点类型是元素的事实。)

找到文本节点。要获取其包含元素,请在路径中再添加一个步骤:

select="preceding-sibling::*/descendant::text()[normalize-space()!=''][last()]/parent::*"

(再次利用父节点的主节点类型为元素的事实。)

如果您打算使用XPath和XSLT,那么值得花一些时间来熟悉谓词。它们允许将复杂约束分层到单个路径中,并且它们为语言增加了很多功能。

答案 1 :(得分:1)

要测试节点是否为文本类型,请在选择器后添加text():

preceding-sibling::text()

在我看来,var2中你需要的只是:

preceding::text()

和var2将是您正在寻找的文本节点。