As the node
elements are guaranteed always to be in groups of 4, the wanted output can be produced by a very simple transformation that doesn't use any grouping method (such as Muenchian or sibling comparison) and is probably more efficient:
<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()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node">
<sample>
<xsl:call-template name="identity"/>
</sample>
</xsl:template>
<xsl:template match="node[not(position() mod 4 = 1)]"/>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<input>
<node>
<id>1</id>
<value>3</value>
</node>
<node>
<id>1</id>
<value>3</value>
</node>
<node>
<id>1</id>
<value>3</value>
</node>
<node>
<id>1</id>
<value>3</value>
</node>
<node>
<id>2</id>
<value>4</value>
</node>
<node>
<id>2</id>
<value>4</value>
</node>
<node>
<id>2</id>
<value>4</value>
</node>
<node>
<id>2</id>
<value>4</value>
</node>
</input>
the wanted, correct result is produced:
<input>
<sample>
<node>
<id>1</id>
<value>3</value>
</node>
</sample>
<sample>
<node>
<id>2</id>
<value>4</value>
</node>
</sample>
</input>
Explanation:
The identity rule copies "as-is" every node for which it is selected for execution.
Another template overrides the identity template for every node
element that is the 4k+1
st node
child of its parent. This template generates a wrapper element (sample
) and then calls the identity template by name to copy itself to the output.
Yet another template overrides the identity template for every node
element. This template matches every node
element but it will be selected for execution (preferred over the previous template), only for nodes not matched by the previous template -- that is for any node
element that is not a 4k+1
st node
child of its parent. This is so, because this template is less specific than the previous template.
The template discussed in 3. above, has no body and this effectively "deletes" the matched node
element from the output.