更新:我为这个问题添加了一个答案,其中包含了几乎所有已给出的建议。下面代码中给出的原始模板需要45605 毫秒才能完成一个真实世界的输入文档(关于脚本编程的英文文本)。社区 wiki 答案中修改后的模板将运行时间降至 605 毫秒!
我正在使用以下 XSLT 模板将字符串中的一些特殊字符替换为其转义变体;它使用分而治之的策略递归地调用自己,最终查看给定字符串中的每个字符。然后它决定是否应该按原样打印字符,或者是否需要任何形式的转义:
<xsl:template name="escape-text">
<xsl:param name="s" select="."/>
<xsl:param name="len" select="string-length($s)"/>
<xsl:choose>
<xsl:when test="$len >= 2">
<xsl:variable name="halflen" select="round($len div 2)"/>
<xsl:variable name="left">
<xsl:call-template name="escape-text">
<xsl:with-param name="s" select="substring($s, 1, $halflen)"/>
<xsl:with-param name="len" select="$halflen"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="right">
<xsl:call-template name="escape-text">
<xsl:with-param name="s" select="substring($s, $halflen + 1)"/>
<xsl:with-param name="len" select="$halflen"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat($left, $right)"/>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$s = '"'">
<xsl:text>"\""</xsl:text>
</xsl:when>
<xsl:when test="$s = '@'">
<xsl:text>"@"</xsl:text>
</xsl:when>
<xsl:when test="$s = '|'">
<xsl:text>"|"</xsl:text>
</xsl:when>
<xsl:when test="$s = '#'">
<xsl:text>"#"</xsl:text>
</xsl:when>
<xsl:when test="$s = '\'">
<xsl:text>"\\"</xsl:text>
</xsl:when>
<xsl:when test="$s = '}'">
<xsl:text>"}"</xsl:text>
</xsl:when>
<xsl:when test="$s = '&'">
<xsl:text>"&"</xsl:text>
</xsl:when>
<xsl:when test="$s = '^'">
<xsl:text>"^"</xsl:text>
</xsl:when>
<xsl:when test="$s = '~'">
<xsl:text>"~"</xsl:text>
</xsl:when>
<xsl:when test="$s = '/'">
<xsl:text>"/"</xsl:text>
</xsl:when>
<xsl:when test="$s = '{'">
<xsl:text>"{"</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$s"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
这个模板占了我的 XSLT 脚本所需的大部分运行时间。将上面的escape-text
模板替换为just
<xsl:template name="escape-text">
<xsl:param name="s" select="."/>
<xsl:value-of select="$s"/>
</xsl:template>
使我的 XSLT 脚本的运行时间在我的一个文档上从 45 秒缩短到不到 1 秒。
因此我的问题是:我怎样才能加快我的escape-text
模板?我正在使用xsltproc,我更喜欢纯 XSLT 1.0 解决方案。XSLT 2.0 解决方案也将受到欢迎。但是,外部库可能对这个项目没有用——尽管我仍然对使用它们的任何解决方案感兴趣。