为什么我的呼叫模板永远循环?

时间:2015-01-26 08:29:06

标签: xslt recursion parameter-passing infinite-loop

我正在将索引字符串转换为索引标记。该字符串可能包含多个级别,以冒号分隔。每个部分也可能有一些其他需要稍后处理的特殊符号。

我的测试字符串是"主页:更改",应转换为:

<indexterm>Home<indexterm>Change</indexterm></indexterm>

我创建了一个没有递归的模板(只做了一个嵌套级别)并且工作正常(注意在调用此模板之前添加了最外层):

    <xsl:template name="parseindexstring">
    <xsl:param name="string"/>
    <xsl:choose>
        <xsl:when test="contains(.,':')">
            <xsl:value-of select="substring-before(.,':')"/>
            <indexterm>
                <xsl:value-of select="substring-after(.,':')"/>
            </indexterm>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="."/>
        </xsl:otherwise>
    </xsl:choose>       
</xsl:template>

但由于我不想将处理限制在一个级别,我决定改为使用递归:

    <xsl:template name="parseindexstring">
    <xsl:param name="string"/>
    <xsl:choose>
        <xsl:when test="contains(.,':')">
            <xsl:value-of select="substring-before(.,':')"/>
            <indexterm>
                <xsl:call-template name="parseindexstring">
                    <xsl:with-param name="string" select="substring-after(.,':')"/>
                </xsl:call-template>
            </indexterm>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="."/>
        </xsl:otherwise>
    </xsl:choose>       
</xsl:template>

这会进入一个无限循环,即使在只有两个级别(即只有一个冒号)的索引字符串上,我也无法找出原因。我将字符串的第二部分传递给嵌套的调用模板,但似乎总是采用顶级调用的字符串参数。至少这就是我在调试器中单步执行XSL的情况。我在这里忘记或误解了什么?

1 个答案:

答案 0 :(得分:1)

问题是你没有在模板中使用string参数,而是使用引用当前上下文的.运算符(我猜的是包含输入字符串的元素) 。由于当前上下文没有变化,表达式contains(.,':')将始终为真,并且模板只是一遍又一遍地处理相同的上下文,而不管string设置为什么。

请尝试使用此模板:

<xsl:template name="parseindexstring">
    <xsl:param name="string"/>
    <xsl:choose>
        <xsl:when test="contains($string,':')">
            <xsl:value-of select="substring-before($string,':')"/>
            <indexterm>
                <xsl:call-template name="parseindexstring">
                    <xsl:with-param name="string" select="substring-after($string,':')"/>
                </xsl:call-template>
            </indexterm>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$string"/>
        </xsl:otherwise>
    </xsl:choose>       
</xsl:template>