【发布时间】:2011-04-03 06:31:24
【问题描述】:
更新:我添加了一个answer to this question,其中包含了几乎所有已给出的建议。下面代码中给出的原始模板需要 45605ms 来完成一个真实世界的输入文档(关于脚本编程的英文文本)。 community wiki answer 中修改后的模板使运行时间降至 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 解决方案也将受到欢迎。但是,外部库可能对这个项目没有用 - 我仍然对使用它们的任何解决方案感兴趣。
【问题讨论】:
-
好问题 (+1)。查看我的答案,速度提高了 17 倍 :)
-
@Frerich-Raabe、@Tomalak、@Alejandro:看我的下一个答案——比@Frerich-Raabe 的最新组合建议解决方案额外加速 1.5 倍。 :) 现在总加速必须超过 100 倍。
标签: string xslt divide-and-conquer