我在 XSLT 中看到了这个递归模板,无法理解发生了什么 [英] I saw this recursion template in XSLT and cannot understand what is happening
问题描述
当控件进入 xsl:variable 时会发生什么?它永远不会到达 <xsl:value-of select="$number * $recursive_result"/>
因为它一次又一次地调用模板,但确实如此.这让我对 XSLT 的整体控制流程产生了疑问.请解释一下!
<xsl:param name="number" select="1"/><xsl:when test="$number < 1"><xsl:value-of select="1"/></xsl:when><xsl:否则><xsl:variable name="recursive_result"><xsl:call-template name="factorial"><xsl:with-param name="number" select="$number - 1"/></xsl:call-template></xsl:变量><xsl:value-of select="$number * $recursive_result"/></xsl:否则></xsl:选择></xsl:模板>
它确实达到了 <xsl:value-of select="$number * $recursive_result"/>
.>
如果你看一下变量声明:
<xsl:call-template name="factorial"><xsl:with-param name="number" select="$number - 1"/></xsl:call-template></xsl:变量>
每次调用模板 factorial 时,传递的参数都会减 1(请看以下指令):
因此,例如,如果模板 factorial
被调用,首先,其值为 3
,到达
并且 factorial
模板的
中的变量调用 再次使用 factorial
模板,但这次的值为 2. 与 1 类似,然后是 0.当以 0
作为值调用时,输入
并为该递归调用实例生成输出 1.然后控制返回到调用模板的位置(factorial
调用的前一个实例).因此,作为下一个指令的
被调用.
这发生在 factorial
调用的所有先前实例中,这些调用递归地调用模板(因此处理每个
的
;xsl:otherwise> 作为
之后的下一条指令.
顺便说一下,您可以通过将
更改为:
<xsl:value-of select="1"/></xsl:when>
要在每次调用时查看变量/值,请使用此 XSLT,它具有打印特定值的
:
<xsl:output method="text" indent="yes"/><xsl:template match="/"><xsl:call-template name="factorial"><xsl:with-param name="number" select="5"/><xsl:with-param name="iteration" select="1"/></xsl:call-template></xsl:模板><xsl:template name="factorial"><xsl:param name="number" select="1"/><xsl:param name="iteration" select="1"/><xsl:when test="$number < 1"><xsl:value-of select="1"/></xsl:when><xsl:否则><xsl:variable name="recursive_result"><xsl:call-template name="factorial"><xsl:with-param name="number" select="$number - 1"/><xsl:with-param name="iteration" select="$iteration + 1"/></xsl:call-template></xsl:变量><xsl:message>迭代次数 = <xsl:value-of select="$iteration"/>;recursive_result = ;结果 = <xsl:value-of select="$number * $recursive_result"/></xsl:message><xsl:value-of select="$number * $recursive_result"/></xsl:否则></xsl:选择></xsl:模板></xsl:transform>
可以通过修改第一个模板中的以下指令来修改需要阶乘的数字:
这是您可以期待的屏幕截图(使用命令行界面,取决于您使用的处理器):
What happens when the control gets into xsl:variable? It should never reach <xsl:value-of select="$number * $recursive_result"/>
as it is calling the template again and again but it does. This made me question the overall control flow of XSLT. Please explain!
<xsl:template name="factorial">
<xsl:param name="number" select="1"/>
<xsl:choose>
<xsl:when test="$number < 1">
<xsl:value-of select="1"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="recursive_result">
<xsl:call-template name="factorial">
<xsl:with-param name="number" select="$number - 1"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$number * $recursive_result"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
It does reach the <xsl:value-of select="$number * $recursive_result"/>
.
If you look at the variable declaration:
<xsl:variable name="recursive_result">
<xsl:call-template name="factorial">
<xsl:with-param name="number" select="$number - 1"/>
</xsl:call-template>
</xsl:variable>
Every time the template, factorial, is called, the parameter being passed is reduced by 1(look at the following instruction):
<xsl:with-param name="number" select="$number - 1"/>
So, for example, if the template factorial
was called, at first, with value of 3
,
the <xsl:otherwise>
is reached and the variable in the factorial
template's <xsl:otherwise>
makes a call to factorial
template again but this time with value as 2. And similarly with 1, and then with 0.
When called with 0
as the value, the <xsl:when>
is entered and the output 1 is produced for that instance of recursive call. Then the control returns to where the template was called from(the previous instance of factorial
call). And hence, the <xsl:value-of>
being the next intruction is called.
This happens to all the previous instances of factorial
calls that called the template recursively(and hence processing <xsl:value-of>
of every <xsl:otherwise>
as being the next instruction after <xsl:variable>
).
By the way, you can save 1 redundant call to the template by changing your <xsl:when>
to:
<xsl:when test="$number <= 1">
<xsl:value-of select="1"/>
</xsl:when>
To have a look at the variables/values at every call use this XSLT, which has <xsl:message>
that prints specific values:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text" indent="yes"/>
<xsl:template match="/">
<xsl:call-template name="factorial">
<xsl:with-param name="number" select="5"/>
<xsl:with-param name="iteration" select="1"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="factorial">
<xsl:param name="number" select="1"/>
<xsl:param name="iteration" select="1"/>
<xsl:choose>
<xsl:when test="$number < 1">
<xsl:value-of select="1"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="recursive_result">
<xsl:call-template name="factorial">
<xsl:with-param name="number" select="$number - 1"/>
<xsl:with-param name="iteration" select="$iteration + 1"/>
</xsl:call-template>
</xsl:variable>
<xsl:message>iteration number = <xsl:value-of select="$iteration"/>; recursive_result = <xsl:value-of select="$recursive_result"/>; result = <xsl:value-of select="$number * $recursive_result"/> </xsl:message>
<xsl:value-of select="$number * $recursive_result"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:transform>
The number for which factorial is desired can by modified by modifying the following instruction in the first template:
<xsl:with-param name="number" select="5"/>
Here is the screenshot of what you can expect(using command line interface, depending on the processor you are using):
这篇关于我在 XSLT 中看到了这个递归模板,无法理解发生了什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!