Group slicing in XSLT with parameters

One other twist on the last slicing stylesheet. Let's say that we didn't want to hard-code the number of items in a group, but instead we wanted to be able to control this separately. We can use an xsl:param on the stylesheet to control this externally and provide a default as well.

Here is the touched up stylesheet, with the changes highlighted.

<xsl:stylesheet version='1.0' xmlns:xsl=''>
 <xsl:output method='xml' indent='yes'/>
 <xsl:param name='itemcount'>2</xsl:param>

 <!-- Just copy everything. -->
 <xsl:template match='@* | node()' mode='everything'>
   <xsl:apply-templates select='@* | node()' mode='everything'/>

 <!-- Copy everything but replace items with the replacement parameter. -->
 <xsl:template match='@* | node()' mode='withreplacement'>
  <xsl:param name='replacement' />
   <!-- Copy everything except item elements. -->
   <xsl:apply-templates select='@* | node()[local-name() != "item"]' mode='withreplacement'>
    <xsl:with-param name='replacement' select='$replacement' />

   <!-- If this is where items are, apply the replacement node-set. -->
   <xsl:if test='item'>
    <xsl:apply-templates select='$replacement' mode='everything' />

 We matched the first of a slice of items.
 Copy everything from the root, passing the current item
 and its sibling(s) as the replacement.
 <xsl:template match='item' mode='firstofslice'>
  <xsl:apply-templates select='/group' mode='withreplacement'>
    select='. | following-sibling::item[position() &lt; $itemcount]'

 <!-- Match to root, and put everything under a single element. -->
 <xsl:template match='/'>
   <!-- Grab every second item to create a new group. -->
   <xsl:apply-templates select='group/item[position() mod $itemcount = 1]' mode='firstofslice' />

By the way, if you haven't already, check out the comments on the first post for a more efficient variation of the stylesheet.


Comments (0)

Skip to main content