使用XSLT对XML条目进行指定次数的转换
与此类似: 。。。但更进一步 我已经有了一个xml文档,其中每个“记录”只包含一次。如果每个记录都有指定的重复次数(每个记录的重复次数不同),那么XSLT是否可以做到这一点 例如:使用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
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>