XSLT: конвертировать отдельные символы строки по отдельности в строку *, включая * их значения в шестнадцатеричном виде - PullRequest
1 голос
/ 31 марта 2019

Мне нужна помощь, преобразование некоторых 8-битных символов ASCII в строку, содержащую их шестнадцатеричное значение.Я хочу преобразовать немецкие умлауты (äöüÄÖÜß) в их шестнадцатеричное RTF представление.Например, символ ä должен быть преобразован в \'E4.

. Я знаю другие решения для преобразования символов, например xslt: преобразование символов в их шестнадцатеричное представление Unicode .Но когда я попытался использовать это в сочетании с xsl:replace(), преобразуется только символ $, а не результат соответствующей группы $0.

Итак, вот что я попробовал.Где-то в таблице стилей я использую это для преобразования некоторых символов строки:

    <xsl:value-of select="replace($rtfText, '[äöüßÄÖÜ]', at:char-to-unicode('$0'))"/>

at:int-to-hex - это функции из другого вопроса.Я подумал, что было бы неплохо использовать его в другой функции:

   <xsl:function name="at:char-to-unicode" as="xs:string">
        <xsl:param name="in" as="xs:string"/>
        <xsl:sequence select="concat('\\''', at:int-to-hex(string-to-codepoints('$in')[1]))"/>
    </xsl:function>

    <xsl:function name="at:int-to-hex" as="xs:string">
        <xsl:param name="in" as="xs:integer"/>
        <xsl:sequence
            select="if ($in eq 0)
            then '0'
            else
            concat(if ($in gt 16)
            then at:int-to-hex($in idiv 16)
            else '',
            substring('0123456789ABCDEF',
            ($in mod 16) + 1, 1))"/>
    </xsl:function>

Кто-нибудь может помочь?

1 Ответ

4 голосов
/ 31 марта 2019

Как вы говорите, вы используете XSLT 2 или 3 и хотите заменить символы в полном выходном документе. Я думаю, что использование карты символов - самый простой подход:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:output method="text" use-character-maps="rtf-hex"/>

  <xsl:character-map name="rtf-hex">
       <xsl:output-character character="ä" string="\'E4"/>
       <xsl:output-character character="ö" string="\'F6"/>
       <xsl:output-character character="ü" string="\'FC"/>
       <xsl:output-character character="Ä" string="\'C4"/>
       <xsl:output-character character="Ö" string="\'D6"/>
       <xsl:output-character character="Ü" string="\'DC"/>
       <xsl:output-character character="ß" string="\'DF"/>
  </xsl:character-map>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net/pPzifpr/1 имеет пример.

В XSLT 3 вы также можете использовать карты символов локально для строки благодаря функциям serialize и второму параметру, в котором вы можете определить символотобразить как XPath 3.1 map(xs:string, xs:string), например,

serialize(., map { "method" : "text", "use-character-maps" : map{"Ä":"\C4","ä":"\E4","Ö":"\D6","ö":"\F6","Ü":"\DC","ü":"\FC","ß":"\DF"} })

, чтобы применить сопоставление, поэтому

<text xml:lang="de">Dies ist ein Test mit Umlauten: ä, ö, ü, ß, Ä, Ö, Ü.</text>

будет преобразовано

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output method="xml"/>

  <xsl:template match="text">
      <xsl:copy>
          <xsl:value-of select='serialize(., map { "method" : "text", "use-character-maps" : map{"Ä":"\C4","ä":"\E4","Ö":"\D6","ö":"\F6","Ü":"\DC","ü":"\FC","ß":"\DF"} })'/>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

в

<text>Dies ist ein Test mit Umlauten: \E4, \F6, \FC, \DF, \C4, \D6, \DC.</text>

Я понимаю, что в последнем примере нет точной замены, которую вы описали, но поскольку я попытался динамически сгенерировать использованную карту и столкнулся с проблемой с Saxon, чтобы сгенерировать правильный синтаксис для использования карты внутри XSLTатрибут, вам нужно будет исправить значения, такие как map{"Ä":"\C4" до map{"Ä":"\&apos;C4".

Что касается сопоставления на основе регулярного выражения и замены их, в XSLT 3.0 с использованием функции analyze-string вы можете использовать

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:function name="mf:int-to-hex" as="xs:string">
      <xsl:param name="int" as="xs:integer"/>
      <xsl:sequence
         select="if ($int eq 0) 
                 then '0' 
                 else concat(
                          if ($int gt 16)
                          then mf:int-to-hex($int idiv 16) else '',
                          substring('0123456789ABCDEF', ($int mod 16) + 1, 1)
                      )"/>
  </xsl:function>

  <xsl:template match="text()">
      <xsl:value-of select="analyze-string(., '\p{IsLatin-1 Supplement}')/*/(if (. instance of element(fn:match)) then '\''' || mf:int-to-hex(string-to-codepoints(.)) else string())" separator=""/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / 94rmq6f

...