0

質問

XSLT 1.0 を使用して、任意の文字を含む文字列を指定すると、次の規則を満たす文字列を取得するにはどうすればよいですか。

  1. 最初の文字は、az、AZ、コロン、またはアンダースコアのいずれかでなければなりません
  2. 他のすべての文字は、上記または 0 ~ 9、ピリオド、またはハイフンのいずれかでなければなりません
  3. 上記の規則を満たさない文字がある場合は、アンダースコアに置き換えます

バックグラウンド

XSLT では、いくつかの属性を要素に変換していますが、要素名で使用できない値が属性に含まれていないことを確認する必要があります。予想どおりに変換されている限り、名前に変換される属性の整合性についてはあまり気にしません。また、要素名のすべての有効な文字を補正する必要もありません(たくさんあります)。

私が抱えていた問題は、変換機能が簡単にアンダースコアに変換できるスペースを含む属性にありました。

translate(@name,' ','_')

しかし、すぐにスラッシュを使用している属性をいくつか見つけたので、それも追加する必要があります。これはすぐに手に負えなくなります。許可された文字のホワイトリストを定義し、許可されていない文字をアンダースコアに置き換えたいと思っていますが、翻訳はブラックリストから置き換えることで機能します。

4

3 に答える 3

6

これを行うための再帰テンプレート作成して、文字列内の文字を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>

注意しなければならない唯一のことは、アンダースコアの文字列は、単一の名前内に表示される可能性のあるすべての不正な文字をカバーするのに十分な長さである必要があるということです。遭遇する可能性のある最長の名前と同じ長さにすると、うまくいきます(ただし、もっと短くすることで解決できる可能性があります)。

于 2008-09-25T09:01:44.360 に答える
1

Imが認識している限り、XSLT1.0にはこのための組み込みがありません。XSLT 2.0を使用すると、正規表現を使用できますが、それを十分に認識していると思います。

万が一、MSパーサーを使用している場合は、XSLTで活用できる.NET拡張ライブラリを作成できます。これについては、数か月前にここで説明しました。

Saxonのようなものを使用している場合、それらは独自の拡張機能をコーディングする方法も提供していると確信しています。実際、すでに独自の拡張機能を持っている可能性がありますが、Imはそのエンジンに慣れていません。

お役に立てれば。

于 2008-09-25T06:10:26.660 に答える
0

もう 1 つの代替手段として、XSLT 標準ライブラリで機能する可能性のある文字列関数があります。http://xsltsl.sourceforge.net/string.html#template.str:string-match

于 2008-09-25T22:24:06.600 に答える