This transformation:
<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>
when applied on the provided XML document:
<?xml version="1.0" encoding="utf-8"?>
<root>
<?PI_start?> SOME TEXT <?PI_end?>
</root>
produces the wanted, correct result:
<root>
<tag> SOME TEXT </tag>
</root>
Do note:
The identity rule is used to copy all nodes "as-is".
We have additional templates only for nodes that should be changed in some way.
The template matching the first PI "does almost all the work". It creates a tag
element and applies templates to the following-sibling node if it is a PI.
We apply templates in mode "copy" for the text node immediate sibling of the first PI.
The mode "copy" isn't declared anywhere and this causes the default template for processing text nodes to be selected -- its action is to just copy the text node. This is a trick that saves us from the need to define a template in the "copy" mode.
We have an empty template that actually deletes the unwanted nodes: the second PI and what would be a second copy of the first PI's immediate-sibling text node.
Update: The OP has indicated that he is also interested in the case where in-between the two PIs there might be different nodes (not only text nodes).
This is a lot more complex task and here is one solution:
<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>
when the above transformation is applied on the following XML document:
<root>
<?PI_start?> <strong>Some</strong> TEXT <?PI_end?> XA <?PI_end?>
</root>
the wanted, correct output is produced:
<root>
<tag>
<strong>Some</strong> TEXT
</tag> XA
</root>
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…