ОБНОВЛЕНИЕ: Я добавил ответ на этот вопрос, который содержит почти все предложения, которые были даны. Исходный шаблон, приведенный в коде ниже, требует 45605ms, чтобы закончить реальный документ ввода (английский текст о программировании script). Пересмотренный шаблон в ответе 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 script. Заменив приведенный выше шаблон escape-text
только
<xsl:template name="escape-text">
<xsl:param name="s" select="."/>
<xsl:value-of select="$s"/>
</xsl:template>
делает время выполнения моего XSLT script переходом от 45 секунд до менее чем одной секунды в одном из моих документов.
Отсюда мой вопрос: как я могу ускорить мой шаблон escape-text
? Я использую xsltproc, и я предпочел бы чистое решение XSLT 1.0. Решения XSLT 2.0 также приветствуются. Тем не менее, внешние библиотеки могут быть не полезны для этого проекта - я все равно буду интересоваться любыми решениями, использующими их, хотя.