4

次のように、XSL translate() 関数を使用して、検索および置換関数のようなものを作成しようとしています。

<xsl:template name="create-id">
    <xsl:param name="id" />
    <xsl:call-template name="search-and-replace">
        <xsl:with-param name="str" select="$id" />
        <xsl:with-param name="search">0123456789</xsl:with-param>
        <xsl:with-param name="replace">abcdefghij</xsl:with-param>
    </xsl:call-template>
</xsl:template>

<xsl:template name="search-and-replace">
    <xsl:param name="str" />
    <xsl:param name="search" />
    <xsl:param name="replace" />
    <xsl:variable name="newstr" select="translate($str, $search,
    $replace)" />
    <xsl:choose>
        <xsl:when test="contains($newstr, $search)">
            <xsl:call-template name="search-and-replace">
                <xsl:with-param name="str" select="$newstr" />
                <xsl:with-param name="search" select="$search" />
                <xsl:with-param name="replace" select="$replace" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$newstr" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

ただし、返された文字列の最後の文字が取り除かれているように見えるため、ここでは私のロジックが間違っています。私の推測では、 translate() は文字列内の各文字の最初のインスタンスを置き換えるだけであり、真に再帰的ではありません。

ご意見やご意見をいただければ幸いです。

4

4 に答える 4

9

このtranslate()関数は、1 つの文字を別の 1 つの文字(または空の文字 (削除))に置き換えることしかできません。したがって、文字列置換の問題を解決できません。

以下は、複数置換問題に対する完全な XSLT 1.0 ソリューションです。

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my">
    <xsl:output omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <my:params xml:space="preserve">
        <pattern>
            <old>&#xA;</old>
            <new><br/></new>
        </pattern>
        <pattern>
            <old>quick</old>
            <new>slow</new>
        </pattern>
        <pattern>
            <old>fox</old>
            <new>elephant</new>
        </pattern>
        <pattern>
            <old>brown</old>
            <new>white</new>
        </pattern>
    </my:params>

    <xsl:variable name="vPats"
         select="document('')/*/my:params/*"/>

    <xsl:template match="text()" name="multiReplace">
        <xsl:param name="pText" select="."/>
        <xsl:param name="pPatterns" select="$vPats"/>

        <xsl:if test="string-length($pText) >0">
            <xsl:variable name="vPat" select=
            "$vPats[starts-with($pText, old)][1]"/>

            <xsl:choose>
                <xsl:when test="not($vPat)">
                    <xsl:copy-of select="substring($pText,1,1)"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="$vPat/new/node()"/>
                </xsl:otherwise>
            </xsl:choose>

            <xsl:call-template name="multiReplace">
                <xsl:with-param name="pText" select=
                "substring($pText, 1 + not($vPat) + string-length($vPat/old/node()))"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

この変換が次の XML ドキュメントに適用された場合:

<t>The quick
brown fox</t>

必要な正しい結果が生成されます。

The slow<br />white elephant

説明:

  1. 自分自身を再帰的に呼び出す名前付きテンプレートが使用されます。

  2. すべての複数の置換パターン --> 置換ペアは、単一の外部パラメーターで提供されます。ここでは便宜上、グローバル レベル要素としてインラインで指定されています<my:params>

  3. 再帰はソース文字列のすべての文字を (左から右に) 取り、文字列内のこの位置でこの文字で始まる最初のパターンを見つけます。

  4. 置換は、文字列だけでなく任意のノードでもかまいません。この特定のケースでは、すべての NL 文字を<br/>要素に置き換えています。

于 2011-03-12T16:24:27.100 に答える
3

translate($arg, $mapString, $transString)関数の定義は次のとおりです。

の値の位置 N にある の値のすべての文字が、 の値の位置 N にある文字に置き換えられる $argように、 の値を変更して返します。$arg$mapString$transString

つまり、部分文字列を別の文字列に置き換えるのではなく、文字を別の文字にマップします。部分文字列の置換には、次のようなものを使用します

<xsl:template name="search-and-replace">
  <xsl:param name="str"/>
  <xsl:param name="search"/>
  <xsl:param name="replace"/>
  <xsl:choose>
    <xsl:when test="contains($str, $search)">
      <xsl:value-of select="substring-before($str, $search)"/>
      <xsl:value-of select="$replace"/>
      <xsl:call-template name="search-and-replace">
        <xsl:with-param name="str" select="substring-after($str, $search)"/>
        <xsl:with-param name="search" select="$search"/>
        <xsl:with-param name="replace" select="$replace"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$str"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>
于 2011-03-12T09:22:04.233 に答える
0

str:exslt から置換します。それはあなたが望むことを正確に行い、xsltの達人によってすでに書かれ、テストされています。xslt ソースもここで入手できます

于 2011-03-12T16:29:50.327 に答える
0

$search のすべての文字を $replace に既に置き換えているため、あなたは決して真実ではないようです

<xsl:variable name="newstr" select="translate($str, $search,
    $replace)" />

予め。

于 2011-03-12T04:16:20.963 に答える