Xml 使用XSLT在循环中每年打印一次
我的源文档包含两个定义范围的值(年)。我把它们放在变量Xml 使用XSLT在循环中每年打印一次,xml,xslt,loops,date-range,Xml,Xslt,Loops,Date Range,我的源文档包含两个定义范围的值(年)。我把它们放在变量$year1和$year2中。我现在需要打印输出这两个值之间每年的-元素,包括开始和结束年份。我看到了一种使用递归创建循环的方法,但特别是看不到如何每次增加一个值。有什么想法吗?XSLT 1.0解决方案 请参阅 当必须生成的序列的大小事先未知且不受限制时,Piez方法不适用 在这种情况下,XSLT解决方案必须使用递归 这里是一个通用的“迭代”模板,它对初始输入执行操作,然后对其结果执行操作,直到指定了给定的条件 此转换是尾部递归的,使用智能X
$year1
和$year2
中。我现在需要打印输出这两个值之间每年的-元素,包括开始和结束年份。我看到了一种使用递归创建循环的方法,但特别是看不到如何每次增加一个值。有什么想法吗?XSLT 1.0解决方案
请参阅
当必须生成的序列的大小事先未知且不受限制时,Piez方法不适用 在这种情况下,XSLT解决方案必须使用递归 这里是一个通用的“迭代”模板,它对初始输入执行操作,然后对其结果执行操作,直到指定了给定的条件 此转换是尾部递归的,使用智能XSLT处理器时不会出现堆栈溢出:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
<xsl:output method="text"/>
<my:action>
<end>1000000</end>
</my:action>
<xsl:variable name="vAction"
select="document('')/*/my:action"/>
<xsl:template match="/">
<xsl:call-template name="iterate">
<xsl:with-param name="pAction" select="$vAction"/>
<xsl:with-param name="pInput" select="0"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="iterate">
<xsl:param name="pAction"/>
<xsl:param name="pInput"/>
<xsl:if test="string-length($pInput)">
<xsl:variable name="vResult">
<xsl:apply-templates select="$pAction">
<xsl:with-param name="pInput" select="$pInput"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:copy-of select="$vResult"/>
<xsl:call-template name="iterate">
<xsl:with-param name="pAction"
select="$pAction"/>
<xsl:with-param name="pInput" select="$vResult"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="my:action">
<xsl:param name="pInput" select="0"/>
<xsl:if test="not($pInput >= end)">
<xsl:value-of select="concat($pInput+1,'
')"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
谢谢你的帮助 我正在使用xslt 2.0,因此Dimitris的最后一个简短说明实现了以下目的:
<xsl:template name="yearranges">
<xsl:param name="year1" />
<xsl:param name="year2" />
<xsl:for-each select="$year1 to $year2">
<year>
<xsl:sequence select="." />
</year>
</xsl:for-each>
</xsl:template>
我每年都要打印a标签。这很简单。更棘手的是,对于xsl:sequence,年份必须格式化为xs:integer,这是在调用模板中完成的:
<xsl:call-template name="yearranges">
<xsl:with-param name="year1" as="xs:integer" select="xs:integer($year1)" />
<xsl:with-param name="year2" as="xs:integer" select="xs:integer($year2)" />
</xsl:call-template>
再次感谢
OliverSean,Piez方法仅适用于具有已知长度限制的序列。这可能不是目前的情况。如果要生成的项目数为数千,该怎么办?请参阅我的答案,了解递归解决方案的两种变体,它们甚至可以对数百万项有效工作。了解递归解决方案可以对数百万项有效,并且在这方面非常有效(时间和空间O(N))。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
<xsl:output method="text"/>
<my:action>
<end>1000000</end>
</my:action>
<xsl:variable name="vAction"
select="document('')/*/my:action"/>
<xsl:template match="/">
<xsl:call-template name="iterate">
<xsl:with-param name="pAction" select="$vAction"/>
<xsl:with-param name="pInput" select="0"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="iterate">
<xsl:param name="pAction"/>
<xsl:param name="pInput"/>
<xsl:if test="string-length($pInput)">
<xsl:variable name="vResult">
<xsl:apply-templates select="$pAction">
<xsl:with-param name="pInput" select="$pInput"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:copy-of select="$vResult"/>
<xsl:call-template name="iterate">
<xsl:with-param name="pAction"
select="$pAction"/>
<xsl:with-param name="pInput" select="$vResult"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="my:action">
<xsl:param name="pInput" select="0"/>
<xsl:if test="not($pInput >= end)">
<xsl:value-of select="concat($pInput+1,'
')"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:call-template name="displayNumbers">
<xsl:with-param name="pStart" select="1"/>
<xsl:with-param name="pEnd" select="1000000"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="displayNumbers">
<xsl:param name="pStart"/>
<xsl:param name="pEnd"/>
<xsl:if test="not($pStart > $pEnd)">
<xsl:choose>
<xsl:when test="$pStart = $pEnd">
<xsl:value-of select="$pStart"/>
<xsl:text>
</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vMid" select=
"floor(($pStart + $pEnd) div 2)"/>
<xsl:call-template name="displayNumbers">
<xsl:with-param name="pStart" select="$pStart"/>
<xsl:with-param name="pEnd" select="$vMid"/>
</xsl:call-template>
<xsl:call-template name="displayNumbers">
<xsl:with-param name="pStart" select="$vMid+1"/>
<xsl:with-param name="pEnd" select="$pEnd"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
<xsl:sequence select="1 to 1000000"/>
<xsl:template name="yearranges">
<xsl:param name="year1" />
<xsl:param name="year2" />
<xsl:for-each select="$year1 to $year2">
<year>
<xsl:sequence select="." />
</year>
</xsl:for-each>
</xsl:template>
<xsl:call-template name="yearranges">
<xsl:with-param name="year1" as="xs:integer" select="xs:integer($year1)" />
<xsl:with-param name="year2" as="xs:integer" select="xs:integer($year2)" />
</xsl:call-template>