Это преобразование :
<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>
Примечание :
Правило идентификации используется для копирования всех узлов "как есть".
У нас есть дополнительные шаблоны только для узлов, которые нужно каким-то образом изменить .
Шаблон, соответствующий первому PI, «выполняет почти всю работу». Создает элемент tag
и применяет шаблоны к узлу следующего брата, если это PI.
Мы применяем шаблоны в режиме «копировать» для текстового узла непосредственного брата первого PI .
Режим «копировать» нигде не объявлен, и это приводит к выбору шаблона по умолчанию для обработки текстовых узлов - его действие заключается в простом копировании текстового узла. Это хитрость, которая избавляет нас от необходимости определять шаблон в режиме «копирования».
У нас есть пустой шаблон, который фактически удаляет нежелательные узлы : второй 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>