Вы могли бы написать рекурсивный шаблон, чтобы сделать это, обрабатывая символы в строке один за другим, проверяя их и изменяя их при необходимости. Что-то вроде:
<xsl:template name="normalizeName">
<xsl:param name="name" />
<xsl:param name="isFirst" select="true()" />
<xsl:if test="$name != ''">
<xsl:variable name="first" select="substring($name, 1, 1)" />
<xsl:variable name="rest" select="substring($name, 2)" />
<xsl:choose>
<xsl:when test="contains('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:_', $first) or
(not($first) and contains('0123456789.-', $first))">
<xsl:value-of select="$first" />
</xsl:when>
<xsl:otherwise>
<xsl:text>_</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="normalizeName">
<xsl:with-param name="name" select="$rest" />
<xsl:with-param name="isFirst" select="false()" />
</xsl:call-template>
</xsl:if>
</xsl:template>
Тем не менее, есть более короткий способ сделать это, если вы готовы к некоторому хакерству. Сначала объявите некоторые переменные:
<xsl:variable name="underscores"
select="'_______________________________________________________'" />
<xsl:variable name="initialNameChars"
select="'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:_'" />
<xsl:variable name="nameChars"
select="concat($initialNameChars, '0123456789.-')" />
Теперь метод заключается в том, чтобы взять имя и идентифицировать символы, которые не являются допустимыми, заменив все символы в имени, которые являются допустимыми, ничем. Вы можете сделать это с помощью функции translate()
. Как только вы получите набор недопустимых символов в строке, вы можете заменить их подчеркиванием, снова используя функцию translate()
. Вот шаблон:
<xsl:template name="normalizeName">
<xsl:param name="name" />
<xsl:variable name="first" select="substring($name, 1, 1)" />
<xsl:variable name="rest" select="substring($name, 2)" />
<xsl:variable name="illegalFirst"
select="translate($first, $initialNameChars, '')" />
<xsl:variable name="illegalRest"
select="translate($rest, $nameChars, '')" />
<xsl:value-of select="concat(translate($first, $illegalFirst, $underscores),
translate($rest, $illegalRest, $underscores))" />
</xsl:template>
Единственное, на что вам следует обратить внимание, это на то, что строка подчеркивания должна быть достаточно длинной, чтобы охватить все недопустимые символы, которые могут появляться в одном имени. Его длина будет соответствовать длине самого длинного имени, с которым вы, вероятно, столкнетесь, и поможет вам (хотя, возможно, вам это и сойдет с рук, намного короче).