web-dev-qa-db-ja.com

XSLT文字列置換

私は実際にはXSLを知りませんが、このコードを修正する必要があります。より簡単にするためにそれを減らしました。
このエラーが発生しています

無効なXSLT/XPath関数

この行に

<xsl:variable name="text" select="replace($text,'a','b')"/>

これがXSLです

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:inm="http://www.inmagic.com/webpublisher/query" version="1.0">
    <xsl:output method="text" encoding="UTF-8" />

    <xsl:preserve-space elements="*" />
    <xsl:template match="text()" />

    <xsl:template match="mos">
        <xsl:apply-templates />

        <xsl:for-each select="mosObj">
          'Notes or subject' 
           <xsl:call-template
                name="rem-html">
                <xsl:with-param name="text" select="SBS_ABSTRACT" />
            </xsl:call-template>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="rem-html">
        <xsl:param name="text" />
        <xsl:variable name="text" select="replace($text, 'a', 'b')" />
    </xsl:template>
</xsl:stylesheet>

誰がそれが間違っているのか教えてもらえますか?

81
Aximili

replaceはXSLT 1.0では使用できません。

Codeslingには string-replaceのテンプレート があり、関数の代替として使用できます。

<xsl:template name="string-replace-all">
    <xsl:param name="text" />
    <xsl:param name="replace" />
    <xsl:param name="by" />
    <xsl:choose>
        <xsl:when test="$text = '' or $replace = ''or not($replace)" >
            <!-- Prevent this routine from hanging -->
            <xsl:value-of select="$text" />
        </xsl:when>
        <xsl:when test="contains($text, $replace)">
            <xsl:value-of select="substring-before($text,$replace)" />
            <xsl:value-of select="$by" />
            <xsl:call-template name="string-replace-all">
                <xsl:with-param name="text" select="substring-after($text,$replace)" />
                <xsl:with-param name="replace" select="$replace" />
                <xsl:with-param name="by" select="$by" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$text" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

として呼び出される:

<xsl:variable name="newtext">
    <xsl:call-template name="string-replace-all">
        <xsl:with-param name="text" select="$text" />
        <xsl:with-param name="replace" select="a" />
        <xsl:with-param name="by" select="b" />
    </xsl:call-template>
</xsl:variable>

一方、文字どおりに1つの文字を別の文字に置き換えるだけの場合は、同様のシグネチャを持つ translate を呼び出すことができます。このような何かがうまくいくはずです:

<xsl:variable name="newtext" select="translate($text,'a','b')"/>

また、この例では、変数名を「newtext」に変更したことに注意してください。XSLT変数は不変であるため、元のコードにあったような$foo = $fooに相当することはできません。

132
Mark Elliot

C#のString.Replace()関数と同様に機能するXSLT関数を次に示します。

このテンプレートには、以下の3つのパラメーターがあります

text:-メイン文字列

replace:-置換したい文字列

by:-新しい文字列で応答する文字列

以下がテンプレートです

<xsl:template name="string-replace-all">
  <xsl:param name="text" />
  <xsl:param name="replace" />
  <xsl:param name="by" />
  <xsl:choose>
    <xsl:when test="contains($text, $replace)">
      <xsl:value-of select="substring-before($text,$replace)" />
      <xsl:value-of select="$by" />
      <xsl:call-template name="string-replace-all">
        <xsl:with-param name="text" select="substring-after($text,$replace)" />
        <xsl:with-param name="replace" select="$replace" />
        <xsl:with-param name="by" select="$by" />
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$text" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

以下のサンプルは、それを呼び出す方法を示しています

<xsl:variable name="myVariable ">
  <xsl:call-template name="string-replace-all">
    <xsl:with-param name="text" select="'This is a {old} text'" />
    <xsl:with-param name="replace" select="'{old}'" />
    <xsl:with-param name="by" select="'New'" />
  </xsl:call-template>
</xsl:variable>

詳細については、 RLの下 を参照することもできます。

35
Optimus

注:ソース文字列の膨大な数のインスタンス(長いテキストの改行など)を置き換える必要がある場合に前述のアルゴリズムを使用する場合は、high再帰呼び出しのためにStackOverflowExceptionになる確率。

Xalanのおかげでこの問題を解決しました(Saxonでそれを行う方法を見ていませんでした)組み込みJavaタイプ埋め込み:

<xsl:stylesheet version="1.0" exclude-result-prefixes="xalan str"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xalan="http://xml.Apache.org/xalan"
                xmlns:str="xalan://Java.lang.String"
        >
...
<xsl:value-of select="str:replaceAll(
    str:new(text()),
    $search_string,
    $replace_string)"/>
...
</xsl:stylesheet>
12
Milan Aleksić

プロセッサが.NETで実行される場合、またはMSXMLを使用する場合(Javaベースまたはその他のネイティブプロセッサとは対照的に)、次のコードを使用できます。 msxsl:script を使用します。

ルートxmlns:msxsl="urn:schemas-Microsoft-com:xslt"またはxsl:stylesheet要素に名前空間xsl:transformを追加してください。

さらに、outletを任意のネームスペース、たとえばxmlns:outlet = "http://my.functions"にバインドします。

<msxsl:script implements-prefix="outlet" language="javascript">
function replace_str(str_text,str_replace,str_by)
{
     return str_text.replace(str_replace,str_by);
}
</msxsl:script>


<xsl:variable name="newtext" select="outlet:replace_str(string(@oldstring),'me','you')" />
6
John Jin

ルーチンはかなり良いですが、それは私のアプリをハングアップさせるので、ケースを追加する必要がありました:

  <xsl:when test="$text = '' or $replace = ''or not($replace)" >
    <xsl:value-of select="$text" />
    <!-- Prevent thsi routine from hanging -->
  </xsl:when>

関数が再帰的に呼び出される前。

私はここから答えを得ました: テストが無限ループにぶら下がっているとき

ありがとうございました!

0
Chesare