xslt递归模板的尾调用优化

时间:2017-05-24 07:54:09

标签: xml xslt nginx tail-recursion libxslt

背景

我们正在使用启用了ngx_http_xslt_module的nginx。这将有助于我们将样式表应用于响应。
该模块在内部使用libxslt处理器来应用xslt转换。它具有可配置的递归深度(maxdepth),超过该递归将发出无限递归错误。

问题

在深度为3000时,当应用于文档时,下面的xslt转换失败并出现无限递归错误。正如我所看到的其他answers,下面的xslt模板是尾调用优化的,并且一些处理器优化了code.Wanted从xslt透视确认下面的xslt函数是否真的经过尾部优化,以及libxslt是否进行尾调用优化。

转换为代码时, escapeQuote xslt模板不是尾部调用优化的。

"currentresult" + escapeQuote(sub-string(str))

以下是用于转义双引号的xslt模板。

 <xsl:template name="escapeQuote">
  <xsl:param name="pText" select="normalize-space(.)"/>
  <xsl:if test="string-length($pText) >0">
   <xsl:value-of select="substring-before(concat($pText, '&quot;'), '&quot;')"/>
   <xsl:if test="contains($pText, '&quot;')">
    <xsl:text>\"</xsl:text>
    <xsl:call-template name="escapeQuote">
      <xsl:with-param name="pText" select="substring-after($pText, '&quot;')"/>
    </xsl:call-template>
   </xsl:if>
  </xsl:if>
</xsl:template>

这是在XSLT 1.0中。

1 个答案:

答案 0 :(得分:0)

libxslt不进行尾调用优化。您应该使用libxslt附带的EXSLT函数。 str:replace函数在技术上不符合规范,但足以满足您的需求。具体而言(假设您尝试将"更改为\"):

<xsl:template xmlns:str="http://exslt.org/strings" name="escapeQuote">
  <xsl:param name="pText" select="normalize-space(.)"/>
  <xsl:value-of select="str:replace($pText,'&quot;','\&quot;')"/>
</xsl:template>

显然你可以放弃所有模板,只需插入相关的XPath,如果这对你更有效。