用一组字符替换一个字符并在xslt中显示消息

时间:2012-11-28 15:37:42

标签: xslt xslt-1.0

输入:

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

输出:

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

要求:

搜索一些特定的字符集,并将其替换为文本“++”。如果遇到charecter需要向用户显示消息。

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>

我没有得到确切的输出。

任何人都可以帮助我。

1 个答案:

答案 0 :(得分:0)

您遇到的第一个问题是翻译功能仅将“单个字符”翻译成另一个字符。所以你不能用它来用双字符串%替换单个字符++。此外,您通常具有相同长度的第二个和第三个参数

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

这是因为'from'字符被'to'字符串中相应位置的字符替换。如果你只是翻译(。,'%^ * @〜','+'),那么字符^*@~将被替换为什么!

XSLT1.0没有替换功能(虽然存在于XSTL2.0中),因此首先需要搜索递归模板来完成这项工作。这是一个!

<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函数将所有有趣的字符替换为一个有趣的字符(例如,%

首先定义一个变量来保存第一个字符参数

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

然后定义两个变量,如此

  <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 变量将设置为%^*@~替换将设置为+++++。然后,您可以使用翻译功能将所有有趣角色的出现替换为相同的角色

translate(., $testvar, $replace)

这意味着您只需要调用替换模板一次

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