0

入力:

<Data>
    <info>the %text ^with *special chars asxbajx @ fagfa ~</info>   
</Data>

出力:

<Data>
    <info> the ++text ++with ++special chars asxbajx ++ fagfa ++</info>
</Data>

要件:

いくつかの特定の文字セットを検索し、それらをテキスト「++」に置き換えます。文字が検出された場合は、ユーザーにメッセージを表示する必要があります。

xslt:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="aaa">

          <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
          <my:pNames>
            <n>%</n>
            <n>^</n>
            <n>*</n>
            <n>@</n>
            <n>~</n>
          </my:pNames>

          <xsl:template match="node() | @*">
            <xsl:copy>
              <xsl:apply-templates select="node() | @*"/>
            </xsl:copy>
          </xsl:template>

          <xsl:template match="text()">

            <xsl:param name="pText" select="."/>


            <xsl:for-each select="document('')/*/my:pNames/n">

              <xsl:variable name="testvar1" select="."/>    
              <xsl:if test="contains($pText,$testvar1)">
                <xsl:message terminate="no">
                 <xsl:value-of select="$pText"/>
                </xsl:message>
              </xsl:if>
            </xsl:for-each>


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

            <xsl:value-of select="
                    translate(
                        .,
                        $testvar,
                        '+'
                        )
                    "/>

          </xsl:template>
        </xsl:stylesheet>

正確な出力が得られません。

誰かが私を助けることができますか?

4

1 に答える 1

0

あなたが持っている最初の問題は、変換関数が単一の文字を別の単一の文字に「変換」するだけであるということです。%したがって、これを使用して1文字を2文字の文字列に置き換えることはできません++。さらに、通常、2番目と3番目の引数は同じ長さです

translate(., '%^*@~', '+++++')

これは、「from」文字が「to」文字列の対応する位置にある文字に置き換えられるためです。translate(。、'%^ * @〜'、'+')だけを実行すると、文字^*@~は何にも置き換えられません。

XSLT1.0には置換関数がありません(XSTL2.0には1つあります)。そのため、最初に再帰テンプレートを探して作業を行う必要があります。これが1つです!

<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> 

パラメータごとに順番に呼び出すのではなく、最初にtranslate関数を使用して、すべての面白い文字を1つの面白い文字に置き換えることができます(たとえば、%

最初に、最初の文字パラメーターを保持する変数を定義します

<xsl:variable name="firstchar" select="document('')/*/my:pNames/n[1]" />

次に、そのように2つの変数を定義します

  <xsl:variable name="testvar">
     <xsl:apply-templates select="document('')/*/my:pNames/n" mode="replace"/>
  </xsl:variable>

  <xsl:variable name="replace">
     <xsl:apply-templates select="document('')/*/my:pNames/n" mode="by"/>
  </xsl:variable>

これに対応するテンプレートは次のようになります

<xsl:template match="my:pNames/n" mode="replace">
   <xsl:value-of select="."/>
</xsl:template>

<xsl:template match="my:pNames/n" mode="by">
   <xsl:value-of select="$firstchar"/>
</xsl:template>

これは、testvar変数がに設定され%^*@~replaceがに設定されることを意味し+++++ます。次に、変換機能を使用して、面白い文字のすべての出現箇所を同じ文字に置き換えることができます

translate(., $testvar, $replace)

これは、置換テンプレートを1回だけ呼び出す必要があることを意味します

  <xsl:call-template name="string-replace-all">
     <xsl:with-param name="text" select="translate(., $testvar, $replace)" />
     <xsl:with-param name="replace" select="$firstchar" />
     <xsl:with-param name="by" select="'++'" />
  </xsl:call-template>

これが完全なXSLTです

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="aaa">
   <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
   <my:pNames>
      <n>%</n>
      <n>^</n>
      <n>*</n>
      <n>@</n>
      <n>~</n>
   </my:pNames>

   <xsl:variable name="firstchar" select="document('')/*/my:pNames/n[1]" />

   <xsl:template match="node() | @*">
      <xsl:copy>
         <xsl:apply-templates select="node() | @*"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="text()">
      <xsl:param name="pText" select="."/>
      <xsl:for-each select="document('')/*/my:pNames/n">
         <xsl:variable name="testvar1" select="."/>
         <xsl:if test="contains($pText,$testvar1)">
            <xsl:message terminate="no">
               <xsl:value-of select="$pText"/>
            </xsl:message>
         </xsl:if>
      </xsl:for-each>

      <xsl:variable name="testvar">
         <xsl:apply-templates select="document('')/*/my:pNames/n" mode="replace"/>
      </xsl:variable>

      <xsl:variable name="replace">
         <xsl:apply-templates select="document('')/*/my:pNames/n" mode="by"/>
      </xsl:variable>

      <xsl:call-template name="string-replace-all">
         <xsl:with-param name="text" select="translate(., $testvar, $replace)" />
         <xsl:with-param name="replace" select="$firstchar" />
         <xsl:with-param name="by" select="'++'" />
      </xsl:call-template>
   </xsl:template>

   <xsl:template match="my:pNames/n" mode="replace">
      <xsl:value-of select="."/>
   </xsl:template>

   <xsl:template match="my:pNames/n" mode="by">
      <xsl:value-of select="$firstchar"/>
   </xsl:template>

   <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:stylesheet>

入力XMLに適用すると、次のように出力されます。

<Data>
   <info>the ++text ++with ++special chars asxbajx ++ fagfa ++</info>
</Data>
于 2012-11-29T09:10:59.320 に答える