Таким образом, XSLT плохо подходит для обработки строк. С XSLT 2.0 все становится лучше, поскольку доступно больше строковых функций и возможны операции на основе последовательностей.
В XSLT 1.0 (который до сих пор является самой переносимой версией для написания кода), посимвольная обработка строки может быть достигнута только посредством рекурсии. Для удовольствия, это:
<xsl:output method="text" />
<xsl:variable name="CRLF" select="' '" />
<xsl:template match="/mytag">
<!-- flip string -->
<xsl:call-template name="reverse-string">
<xsl:with-param name="s" select="string(.)" />
</xsl:call-template>
<xsl:value-of select="$CRLF" />
<!-- vertical string -->
<xsl:call-template name="vertical-string">
<xsl:with-param name="s" select="string(.)" />
</xsl:call-template>
</xsl:template>
<xsl:template name="reverse-string">
<xsl:param name="s" select="''" />
<xsl:variable name="l" select="string-length($s)" />
<xsl:value-of select="substring($s, $l, 1)" />
<xsl:if test="$l > 0">
<xsl:call-template name="reverse-string">
<xsl:with-param name="s" select="substring($s, 1, $l - 1)" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="vertical-string">
<xsl:param name="s" select="''" />
<xsl:variable name="l" select="string-length($s)" />
<xsl:value-of select="concat(substring($s, 1, 1), $CRLF)" />
<xsl:if test="$l > 0">
<xsl:call-template name="vertical-string">
<xsl:with-param name="s" select="substring($s, 2, $l)" />
</xsl:call-template>
</xsl:if>
</xsl:template>
Производит:
ataD modnaR
R
a
n
d
o
m
D
a
t
a
РЕДАКТИРОВАТЬ: Для ясности: я не поддерживаю фактическое использование приведенного выше примера кода в любом случае. Вопросы представления должны быть непременно решены на уровне представления. Вышеприведенное сработает, но рекурсия по типу char-to-char является одним из самых неэффективных способов обработки строк, и, если у вас нет другого выбора, избегайте обработки строк в XSLT.