更新:私はこの質問への回答を追加しました。これには、与えられたほとんどすべての提案が組み込まれています。以下のコードに示されている元のテンプレートは、実際の入力ドキュメント(スクリプトプログラミングに関する英語のテキスト)を完成させるために45605msを必要としました。コミュニティウィキの回答の改訂されたテンプレートにより、実行時間が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
テンプレートを
<xsl:template name="escape-text">
<xsl:param name="s" select="."/>
<xsl:value-of select="$s"/>
</xsl:template>
XSLTスクリプトの実行時間が、ドキュメントの1つで45秒から1秒未満になります。
したがって、私の質問:escape-text
テンプレートを高速化するにはどうすればよいですか?私はxsltprocを使用しており、純粋なXSLT1.0ソリューションを好みます。XSLT2.0ソリューションも歓迎されます。ただし、外部ライブラリはこのプロジェクトには役立たない可能性があります。それでも、外部ライブラリを使用するソリューションには興味があります。