使用XSLT对XML条目进行指定次数的转换

使用XSLT对XML条目进行指定次数的转换,xml,xslt,Xml,Xslt,与此类似: 。。。但更进一步 我已经有了一个xml文档,其中每个“记录”只包含一次。如果每个记录都有指定的重复次数(每个记录的重复次数不同),那么XSLT是否可以做到这一点 例如: 10 值1 价值2 5. 值1 价值2 8. 值1 价值2 26 值1 价值2 使用XSLT 3(由Saxon 9.8 all Edition或Altova 2017和2018支持),您可以尽可能简洁地编写它 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999

与此类似:

。。。但更进一步

我已经有了一个xml文档,其中每个“记录”只包含一次。如果每个记录都有指定的重复次数(每个记录的重复次数不同),那么XSLT是否可以做到这一点

例如:


10
值1
价值2
5.
值1
价值2
8.
值1
价值2
26
值1
价值2
使用XSLT 3(由Saxon 9.8 all Edition或Altova 2017和2018支持),您可以尽可能简洁地编写它

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:mode on-no-match="shallow-copy" streamable="yes"/>

    <xsl:output indent="yes"/>

    <xsl:template match="Parent">
        <xsl:copy>
            <xsl:copy-of select="Record!copy-of()!(let $r := . return (1 to repeat)!$r)"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
此外,正如评论中正确指出的那样,正常处理不需要
copy-of()
,只需要流式处理,因此如果
xsl:mode
上没有
streamable=“yes”
,模板可以编写为

<xsl:template match="Record">
    <xsl:copy-of select="(1 to repeat)!current()"/>     
</xsl:template>

使用XSLT2,您可以使用

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:output indent="yes"/>

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

    <xsl:template match="Record">
        <xsl:copy-of select="for $n in 1 to repeat return current()"/>     
    </xsl:template>

</xsl:stylesheet>

如果您正在使用XSLT 1.0,请升级到XSLT 2.0

但如果不可能,那么在XSLT1.0中可以使用递归命名模板

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

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

    <xsl:template match="Record">
        <xsl:call-template name="Repeat">
            <xsl:with-param name="repeat" select="repeat" />
        </xsl:call-template>
    </xsl:template>

    <xsl:template match="repeat" />

    <xsl:template name="Repeat">
        <xsl:param name="repeat" />

        <xsl:call-template name="Identity" />
        <xsl:if test="$repeat > 1">
            <xsl:call-template name="Repeat">
                <xsl:with-param name="repeat" select="$repeat - 1" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

您能使用XSLT2.0吗?在这个阶段…不知道,只是希望看看有什么可能。在这方面有很多东西要学!我不明白为什么需要调用
copy-of()
函数?您也可以执行
@MichaelKay,因为我试图使其
可流化=“yes”
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*" />

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

    <xsl:template match="Record">
        <xsl:call-template name="Repeat">
            <xsl:with-param name="repeat" select="repeat" />
        </xsl:call-template>
    </xsl:template>

    <xsl:template match="repeat" />

    <xsl:template name="Repeat">
        <xsl:param name="repeat" />

        <xsl:call-template name="Identity" />
        <xsl:if test="$repeat > 1">
            <xsl:call-template name="Repeat">
                <xsl:with-param name="repeat" select="$repeat - 1" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*" />

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

    <xsl:template match="Record">
        <xsl:variable name="Record" select="." />
        <xsl:for-each select="1 to xs:integer(repeat)">
            <xsl:apply-templates select="$Record" mode="Repeat" />
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="repeat" />

    <xsl:template match="*" mode="Repeat">
        <xsl:call-template name="Identity" />
    </xsl:template>
</xsl:stylesheet>