Обработка инструкции преобразования - PullRequest
6 голосов
/ 12 ноября 2010

Я хочу преобразовать инструкции обработки в исходном XML-коде в какой-либо тег в выводе

Ввод

<?xml version="1.0" encoding="utf-8"?>
<root>
    <?PI_start?> SOME TEXT <?PI_end?>
</root>

Я хочу получить выводxml вот так

<root>
    <tag> SOME TEXT </tag>
</root>

Могу ли я это сделать?Если да, что xsl я должен использовать для преобразования?

Я нашел только способ преобразовать PI в открывающий и закрывающий теги.PI может содержать некоторое содержимое.

Входной XML

<root>
    <?PI SOME TEXT?>
</root>

XSL

<xsl:template match="processing-instruction('PI')">
    <tag><xsl:value-of select="."/></tag>
</xsl:template>

Выход

<tag>SOME TEXT</tag>

Но это не мой случай

Ответы [ 2 ]

10 голосов
/ 12 ноября 2010

Это преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="processing-instruction('PI_start')">
  <tag>
   <xsl:apply-templates mode="copy" select=
       "following-sibling::node()[1][self::text()]"/>
  </tag>
 </xsl:template>

 <xsl:template match=
 "processing-instruction('PI_end')
 |
  text()[preceding-sibling::node()[1]
              [self::processing-instruction('PI_start')]]
 "/>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<?xml version="1.0" encoding="utf-8"?>
<root>
    <?PI_start?> SOME TEXT <?PI_end?>
</root>

дает желаемый, правильный результат :

<root>
   <tag> SOME TEXT </tag>
</root>

Примечание :

  1. Правило идентификации используется для копирования всех узлов "как есть".

  2. У нас есть дополнительные шаблоны только для узлов, которые нужно каким-то образом изменить .

  3. Шаблон, соответствующий первому PI, «выполняет почти всю работу». Создает элемент tag и применяет шаблоны к узлу следующего брата, если это PI.

  4. Мы применяем шаблоны в режиме «копировать» для текстового узла непосредственного брата первого PI .

  5. Режим «копировать» нигде не объявлен, и это приводит к выбору шаблона по умолчанию для обработки текстовых узлов - его действие заключается в простом копировании текстового узла. Это хитрость, которая избавляет нас от необходимости определять шаблон в режиме «копирования».

  6. У нас есть пустой шаблон, который фактически удаляет нежелательные узлы : второй PI и что будет второй копией текстового узла непосредственного брата первого PI.

Обновление : ОП указал, что ему также интересен случай, когда между двумя PI могут быть разные узлы (не только текстовые узлы).

Это намного более сложная задача, и вот одно из решений:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kSurrounded" match="node()"
  use="concat(
        generate-id(preceding-sibling::processing-instruction('PI_start')[1]),
        '+++',
        generate-id(following-sibling::processing-instruction('PI_end')[1])
             )"/>

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

 <xsl:template match="processing-instruction('PI_start')">
  <tag>
   <xsl:apply-templates mode="copy" select=
       "key('kSurrounded',
             concat(generate-id(),
                   '+++',
                   generate-id(following-sibling::processing-instruction('PI_end')[1])
                   )
             )"/>
  </tag>
 </xsl:template>

 <xsl:template match=
 "processing-instruction('PI_end')
 |
  node()[(preceding-sibling::processing-instruction('PI_start')
         |
          preceding-sibling::processing-instruction('PI_end')
          )
           [last()][self::processing-instruction('PI_start')]
        and
         (following-sibling::processing-instruction('PI_start')
        |
          following-sibling::processing-instruction('PI_end')
          )
           [1][self::processing-instruction('PI_end')]
        ]
 "/>

 <xsl:template match="node()" mode="copy">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>

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

<root>
    <?PI_start?> <strong>Some</strong> TEXT <?PI_end?> XA <?PI_end?>
</root>

желаемый, правильный вывод производится :

<root>
    <tag>
        <strong>Some</strong> TEXT 
    </tag> XA 
</root>
1 голос
/ 17 ноября 2010

Я предлагаю другой способ решения моей проблемы.Я надеюсь, что это правильно

<xsl:stylesheet version="1.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="processing-instruction('PI_start')">
    <xsl:text disable-output-escaping="yes"><![CDATA[<tag>]]></xsl:text>
</xsl:template>

<xsl:template match="processing-instruction('PI_end')">
    <xsl:text disable-output-escaping="yes"><![CDATA[</tag>]]></xsl:text>
</xsl:template>

Ввод

<root>
    <?PI_start?> <strong>Some</strong> TEXT <?PI_end?> XA <?PI_end?>
</root>

Получен правильный вывод

<root>
    <tag> <strong>Some</strong> TEXT </tag> XA </tag>
</root>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...