これを行うための再帰テンプレートを作成して、文字列内の文字を1つずつ処理し、テストして、必要に応じて変更することができます。何かのようなもの:
<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>
注意しなければならない唯一のことは、アンダースコアの文字列は、単一の名前内に表示される可能性のあるすべての不正な文字をカバーするのに十分な長さである必要があるということです。遭遇する可能性のある最長の名前と同じ長さにすると、うまくいきます(ただし、もっと短くすることで解決できる可能性があります)。