Как я могу заменить определенные символы на их экранированные варианты, используя XSLT? - PullRequest
4 голосов
/ 19 августа 2010

Я пытаюсь разработать таблицу стилей 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 Ответ

4 голосов
/ 19 августа 2010

В частности, символы

/ | & { } # @ ~ \ " 

должны быть заключены в двойные кавычки ("), чтобы хам рассматривал их как обычные символы.

I. Это проще всего сделать, используя str-map шаблон FXSL :

<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...