Как посчитать количество выходных узлов, используя XSLT? - PullRequest
0 голосов
/ 01 июля 2019

Мне нужно посчитать количество узлов из выходного файла. Я выполняю некоторые манипуляции с данными (создаю новую структуру из узлов), как вы можете видеть ниже:

<?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 голосов
/ 01 июля 2019

Вы можете использовать следующую таблицу стилей XSLT-1.0.
Он использует рекурсивный шаблон tokens для перебора значений, разделенных запятыми. Кроме того, количество обработанных элементов вычисляется путем вычитания строки без запятых из всей строки (с исключением xsl: select в случае пустой строки). Остальная часть вашего шаблона остается неизменной.

<?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 или выше, этот код может быть синтаксически сжат.

...