【问题标题】:Why is my call-template looping forever?为什么我的调用模板永远循环?
【发布时间】:2015-01-26 08:29:05
【问题描述】:

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

我的测试字符串是“Home:Change”,应该转换成:

<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,它看起来就是这样。我在这里忘记或误解了什么?

【问题讨论】:

    标签: xslt recursion parameter-passing infinite-loop


    【解决方案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>
    

    【讨论】:

    • 是的。这样可行。如果我理解正确,match-template 会将上下文更改为标记为要处理的选择的任何内容,并且 call-template 不会更改上下文。这对我来说很有意义。非常感谢您的帮助。
    猜你喜欢
    • 2013-10-02
    • 2021-10-04
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 2018-08-14
    • 2021-03-20
    • 1970-01-01
    • 2011-10-28
    相关资源
    最近更新 更多