如何使用XSLT计算输出节点的数量?

时间:2019-06-30 22:54:55

标签: xslt xslt-1.0

我需要计算输出文件中的节点数。我进行了一些数据操作(从节点创建新结构),如下所示:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="no" indent="yes" method="xml"/>

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

    <xsl:strip-space elements="*"/>


    <xsl:template match="resources">
        <xsl:param name="pIndex" select="0"/>
        <xsl:variable name="vToken" select="substring-before(substring(concat(.,','), $pIndex+1), ',')"/>
        <xsl:variable name="vnewIndex" select="$pIndex+string-length($vToken)+1"/>
        <resource_code>
            <xsl:value-of select="normalize-space($vToken)"/>
        </resource_code>
        <xsl:apply-templates select="self::node()[not($vnewIndex >= string-length(.))]">
            <xsl:with-param name="pIndex" select="$vnewIndex"/>
        </xsl:apply-templates>
    </xsl:template>

我的输入文件是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <resources>
        <resource_code>Truck, Van</resource_code>
    </resources>
</root>

上面显示的xsl代码向我返回:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <resources>
        <resource_code>Truck</resource_code>
        <resource_code>Van</resource_code>
    </resources>
</root>

我想计算输出文件中标签的数量,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <resources>
        <resource_code>Truck</resource_code>
        <resource_code>Van</resource_code>
    </resources>
    <nofresources>2</nofresources>
</root>

我该怎么做?我正在使用xslt 1.0!

1 个答案:

答案 0 :(得分:0)

您可以使用以下XSLT-1.0样式表。
它使用递归模板tokens迭代逗号分隔的值。此外,通过从整个字符串中减去不带逗号的字符串来计算处理的项目量(如果为空,则为xsl:choose例外)。模板的其余部分保持不变。

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="no" indent="yes" method="xml"/>

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

    <xsl:strip-space elements="*"/>

    <xsl:template match="resources">
        <xsl:copy>
            <!-- Process all subtrings of resource_code items -->
            <xsl:call-template name="tokens">
                <xsl:with-param name="pStr" select="concat(resource_code,',')" />
            </xsl:call-template>
        </xsl:copy>
        <xsl:choose>
            <xsl:when test="normalize-space(resource_code) = ''">
                <nofresources>0</nofresources>
            </xsl:when>
            <xsl:otherwise>
                <nofresources><xsl:value-of select="string-length(resource_code) - string-length(translate(resource_code,',','')) + 1" /></nofresources>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!-- Recursive template over pStr items delimited by commatas -->
    <xsl:template name="tokens">
        <xsl:param name="pStr" />
        <!-- Set variable to string before comma -->
        <xsl:variable name="vToken" select="substring-before($pStr,',')" />
        <!-- If string is not last string ... -->
        <xsl:if test="$vToken != ''">
            <!-- Add element with value -->
            <resource_code><xsl:value-of select="normalize-space($vToken)"/></resource_code>
            <!-- Recursive call with rest of string as parameter -->
            <xsl:call-template name="tokens">
                <xsl:with-param name="pStr" select="substring-after($pStr,',')" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

其输出为:

<?xml version="1.0"?>
<root>
    <resources>
        <resource_code>Truck</resource_code>
        <resource_code>Van</resource_code>
    </resources>
    <nofresources>2</nofresources>
</root>

如果您可以使用XSLT-2.0或更高版本,则可以对这些代码进行语法压缩。