如何使用XSLT用转义的变体替换某些字符?

时间:2010-08-18 22:38:08

标签: xslt escaping

我正在尝试开发一个XSLT样式表,它将给定的DocBook文档转换为一个文件,该文件可以提供给lout文档格式化系统(然后生成PostScript输出)。

这样做需要我替换DocBook元素文本中的几个字符,因为它们对lout具有特殊含义。特别是字符

/ | & { } # @ ~ \ "

需要用双引号(“)括起来,以便lout将它们视为普通字符。

例如,像

这样的DocBook元素
<para>This is a sample {a contrived one at that} ~ it serves no special purpose.</para>

应该转换为

@PP
This is a sample "{"a contrived one at that"}" "~" it serves no special purpose.

如何使用XSLT执行此操作?我正在使用xsltproc,因此使用XPath 2.0函数不是一个选项,但可以使用许多EXSLT函数。

我尝试使用递归模板生成子字符串,直到特殊字符(例如{),然后是转义字符序列("{"),然后在特殊字符后面的子字符串上调用自身。但是,在尝试替换多个字符时,我很难使其正常工作,其中一个字符用于转义序列本身。

1 个答案:

答案 0 :(得分:4)

  

特别是字符

/ | & { } # @ ~ \ " 
     

需要用双引号括起来   (“)以便lout将它们视为   普通人物。

<强>予。使用 FXSL str-map模板可以轻松完成此操作:

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:f="http://fxsl.sf.net/"
 xmlns:strmap="strmap"
 exclude-result-prefixes="xsl f strmap">
   <xsl:import href="str-dvc-map.xsl"/>

   <xsl:output method="text"/>

   <strmap:strmap/>

   <xsl:template match="/">
     <xsl:variable name="vMapFun" select="document('')/*/strmap:*[1]"/>
     @PP
     <xsl:call-template name="str-map">
       <xsl:with-param name="pFun" select="$vMapFun"/>
       <xsl:with-param name="pStr" select="."/>
     </xsl:call-template>
   </xsl:template>

    <xsl:template name="escape" match="strmap:*" mode="f:FXSL">
      <xsl:param name="arg1"/>

      <xsl:variable name="vspecChars">/|&amp;{}#@~\"</xsl:variable>

      <xsl:variable name="vEscaping" select=
       "substring('&quot;', 1 div contains($vspecChars, $arg1))
       "/>

      <xsl:value-of select=
      "concat($vEscaping, $arg1, $vEscaping)"/>
    </xsl:template>

</xsl:stylesheet>

在提供的XML文档上使用此转换时

<para>This is a sample {a contrived one at that} ~ it serves no special purpose.</para>

产生了想要的正确结果

@PP  这是一个样本“{”一个人为的“}”“〜”它没有任何特殊目的。

<强> II。使用XSLT 1.0递归命名模板:

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="text"/>

   <xsl:template match="/">
     @PP
     <xsl:call-template name="escape">
       <xsl:with-param name="pStr" select="."/>
     </xsl:call-template>
   </xsl:template>

    <xsl:template name="escape">
     <xsl:param name="pStr" select="."/>
     <xsl:param name="pspecChars">/|&amp;{}#@~\"</xsl:param>

     <xsl:if test="string-length($pStr)">
         <xsl:variable name="vchar1" select="substring($pStr,1,1)"/>

          <xsl:variable name="vEscaping" select=
           "substring('&quot;', 1 div contains($pspecChars, $vchar1))
           "/>

          <xsl:value-of select=
          "concat($vEscaping, $vchar1, $vEscaping)"/>

          <xsl:call-template name="escape">
           <xsl:with-param name="pStr" select="substring($pStr,2)"/>
           <xsl:with-param name="pspecChars" select="$pspecChars"/>
          </xsl:call-template>
      </xsl:if>
    </xsl:template>
</xsl:stylesheet>