Currently selected solution :
//comment()/following-sibling::*[1]/self::item
does not work if there is a processing instruction (or a whole group of processing instructions) between the comment and the element, as noted in the comment of Martin Honnen.
The solution below does not have such a problem .
In the following XPath expression, only node nodes are selected that either immediately precede the node comment or immediately preceded only by a space with a node followed by the node comment immediately:
(//comment() /following-sibling::node() [1] [self::text() and not(normalize-space()) ] /following-sibling::node() [1] [self::item] ) | (//comment() /following-sibling::node() [1] [self::item] )
Here is the full test :
We use this XML document:
<root> <list> <item name="foo" /> <item name="bar" /> <item name="another foo" /> <item name="immed.after 3"/> <?PI ?><item name="after PI"/> </list> </root>
When the following conversion applies to the above XML document :
<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="/"> <xsl:copy-of select= " (//comment() /following-sibling::node() [1] [self::text() and not(normalize-space()) ] /following-sibling::node() [1] [self::item] ) | (//comment() /following-sibling::node() [1] [self::item] ) "/> </xsl:template> </xsl:stylesheet>
required, the correct result is obtained :
<item name="foo"/> <item name="another foo"/> <item name="immed.after 3"/>
Dimitre novatchev
source share