Как мне «смешать и сопоставить» трансляцию сущностей в функции XSLT2 replace ()? - PullRequest
3 голосов
/ 18 января 2012

Я экспериментирую с XSLT2, использую таблицу стилей на основе этого ответа:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
 <xsl:template match="source/text()">
  <xsl:sequence select="replace(., '&lt;.*?&gt;', '<ph>$0</ph>')"/>
 </xsl:template>
</xsl:stylesheet>

, который предназначен для многократной замены, например, из:

<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns:xliff="urn:oasis:names:tc:xliff:document:1.1" version="1.1">
  <file>
    <source>abc &lt;field1&gt; def &lt;field2&gt; ghi</source>
  </file>
</xliff>

до:

<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns:xliff="urn:oasis:names:tc:xliff:document:1.1" version="1.1">
  <file>
    <source>abc <ph>&lt;field1&gt;</ph> def <ph>&lt;field2&gt;</ph> ghi</source>
  </file>
</xliff>

Однако мое преобразование недопустимо, я получаю эту ошибку:

Error on line 12 column 54 of my.xsl:
  SXXP0003: Error reported by XML parser: The value of attribute "select" associated with an
  element type "null" must not contain the '<' character.

Если я использую select="replace(., '&lt;(.*?)&gt;', '&lt;ph&gt;F&lt;/phgt;')", тогда я получаю ...&lt;ph&gt;... на выходе.

Если я использую DOE , я создаю другие проблемы, потому что могут быть другие объекты в поле, которые я хочу оставить нетронутыми Если я использую <xsl:output method="text"/>, я теряю большую часть своего xml - есть ли другой способ «смешивания и сопоставления», подобный этому?

Ответы [ 2 ]

4 голосов
/ 18 января 2012

Проблема здесь :

<xsl:sequence select="replace(., '&lt;(.*?)&gt;', '<ph>F</ph>')"/>

Правильно сформированный XML-документ не может содержать символ < в значении атрибута .

В этом конкретном случае вышеприведенный атрибут select содержит подстроку <ph>F</ph>, и это приводит к тому, что таблица стилей даже не анализируется как документ XML.

И, что более важно, элементыне может быть сгенерировано просто путем замены строки - результатом будет просто строка (содержащая представление закодированного элемента) - не элемент.

Вот как можно добиться того, чего вы хотите :

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

 <xsl:template match="source/text()">
  <xsl:analyze-string select="." regex="&lt;(.*?)&gt;">
    <xsl:matching-substring>
      <ph><xsl:value-of select="regex-group(1)"/></ph>
    </xsl:matching-substring>
    <xsl:non-matching-substring>
     <xsl:sequence select="."/>
    </xsl:non-matching-substring>
  </xsl:analyze-string>
 </xsl:template>

, когда это преобразование применяется к предоставленному документу XML :

<xliff xmlns:xliff="urn:oasis:names:tc:xliff:document:1.1" version="1.1">
    <file>
        <source>abc &lt;field1&gt; def &lt;field2&gt; ghi</source>
    </file>
</xliff>

желаемый результат получается :

<xliff xmlns:xliff="urn:oasis:names:tc:xliff:document:1.1" version="1.1">
      <file>
            <source>abc <ph>field1</ph> def <ph>field2</ph> ghi</source>
      </file>
</xliff>

Пояснение : правильное использование инструкций XSLT 2.0 <xsl:analyze-string>, <xsl:matching-substring>, <xsl:non-matching-substring> и regex-group()

1 голос
/ 18 января 2012

Если в исходном документе появляется строка &lt;, то в представлении документа XDM-дерева на его месте будет находиться символ «<», который будет соответствовать регулярному выражению «<», которое записано в вашей таблице стилей как<code>&lt;.

Так что должно сработать, но вы, очевидно, сделали что-то не так.Покажите нам, что вы сделали, и мы могли бы рассказать вам, где вы ошиблись.Сказать нам, что вы столкнулись с проблемами, бесполезно, если вы не сообщите нам, в чем заключались проблемы.

...