I. The XSLT 1.0 solution is much simpler and shorter :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:key name="kFollowing" match="elseif|else" use="generate-id(preceding-sibling::if[1])"/> <xsl:template match="/*"> <rules> <xsl:apply-templates select="if"/> </rules> </xsl:template> <xsl:template match="if"> <conditionSet> <xsl:copy-of select=".|key('kFollowing', generate-id())"/> </conditionSet> </xsl:template> </xsl:stylesheet>
when applied to the provided XML document :
<rules> <if condition="equals" arg1="somevar" arg2="1"/> <elseif condition="equals" arg1="somevar" arg2="2"/> <elseif condition="equals" arg1="somevar" arg2="3"/> <else/> <if condition="equals" arg1="somevar" arg2="4"/> <else/> </rules>
required, the correct result is obtained :
<rules> <conditionSet> <if condition="equals" arg1="somevar" arg2="1"/> <elseif condition="equals" arg1="somevar" arg2="2"/> <elseif condition="equals" arg1="somevar" arg2="3"/> <else/> </conditionSet> <conditionSet> <if condition="equals" arg1="somevar" arg2="4"/> <else/> </conditionSet> </rules>
II. An even simpler and faster XSLT 2.0 solution :
<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="/*"> <rules> <xsl:for-each-group select="*" group-starting-with="if"> <conditionSet> <xsl:sequence select="current-group()"/> </conditionSet> </xsl:for-each-group> </rules> </xsl:template> </xsl:stylesheet>
when this conversion is applied to the same XML document (above), the same correct result is obtained :
<rules> <conditionSet> <if condition="equals" arg1="somevar" arg2="1"/> <elseif condition="equals" arg1="somevar" arg2="2"/> <elseif condition="equals" arg1="somevar" arg2="3"/> <else/> </conditionSet> <conditionSet> <if condition="equals" arg1="somevar" arg2="4"/> <else/> </conditionSet> </rules>
source share