xslt 2.0 - 从递归结构中获取最新节点

xslt 2.0 - get latest node from recursive structure

我想在递归节点结构中搜索特定节点并从最新节点中读取值。我尝试过的解决方案是通过搜索条件递归调用模板,然后将结果放入变量,然后通过 for-each 遍历变量。 例如,my.xml:

<test>
    <test>
        <test>
            <test result='passed'>
                <metadata data='1'/>
            </test>
            <test result='passed'>
                <metadata data='2'/>
            </test>
            <test result='passed'>
                <metadata data='3'/>
            </test>
        </test>
    </test>
</test>

my.xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template name="my_template">
        <xsl:param name="node"/>
        <xsl:if test="$node/@result and $node/@result != 'undefined'">
            <xsl:value-of select="./metadata/@data"/>
        </xsl:if>
        <xsl:for-each select="$node/test">
            <xsl:call-template name="my_template">
                <xsl:with-param name="node" select="." />
            </xsl:call-template>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="/">
        <xsl:variable name="var">
            <xsl:call-template name="my_template">
              <xsl:with-param name="node" select="."/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:for-each select="$var">
            <xsl:if test="position() = last()">
                <xsl:value-of select="."/>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

我得到的结果:

123

但我预计只会得到“3”

我做错了什么?

变量 $var 似乎得到“123”作为单个值,如果我在 之后添加“,”,我得到“123,”。我希望在 $var 中获得一组节点来提取最新值。

也许还有其他方法可以解决任务?谢谢!

似乎使用 last() 的简单路径表达式会给您结果:

<xsl:value-of select="(//test[@result and @result != 'undefined'])[last()]/metadata/@data"/>

https://xsltfiddle.liberty-development.net/94AbWBo

如果您使用模板并想要 return 一系列属性节点,并且还想将它们存储为您可以访问的序列,那么您需要使用 as 属性,例如

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:template name="my_template">
        <xsl:param name="node"/>
        <xsl:if test="$node/@result and $node/@result != 'undefined'">
            <xsl:sequence select="./metadata/@data"/>
        </xsl:if>
        <xsl:for-each select="$node/test">
            <xsl:call-template name="my_template">
                <xsl:with-param name="node" select="." />
            </xsl:call-template>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="/">
        <xsl:variable name="var" as="attribute()*">
            <xsl:call-template name="my_template">
              <xsl:with-param name="node" select="."/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:value-of select="$var[last()]"/>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/94AbWBo/2