RE: [xsl] Splitting data into smaller groups for HTML output.

Subject: RE: [xsl] Splitting data into smaller groups for HTML output.
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Mon, 31 Oct 2005 19:36:20 -0000
> The way I'm looking to split the items into groups is as follows.
> 
> 1 to 5 items - 1 group
> 6 to 10 items - 2 groups
> 11 to 15 items - 3 groups
> 16 - 20 items - 4 groups
> 21 - 25 items - 5 groups

Or to put it another way, the number of groups $n is floor(((count(items)-1)
div 5) + 1)

This still isn't quite a complete spec: if there are 21 items, are your 5
groups of size 5/4/4/4/4, or of size 5/5/5/5/1?

If we assume the latter (because it's easier) then in XSLT 2.0 you end up
with 

<xsl:variable name="all-items" select="..."/>
<xsl:variable name="num-groups" select="floor(((count($all-items)-1) div 5)
+ 1)"/>
<xsl:for-each select="1 to $n">
  <div>
    <xsl:copy-of select="subsequence($items, (. - 1)*5 + 1, 5)"/>
  </div>
</xsl:for-each>

In 1.0 it's a bit more convoluted: the equivalent is along the lines

<xsl:variable name="all-items" select="..."/>
<xsl:variable name="num-groups" select="floor(((count($all-items)-1) div 5)
+ 1)"/>
<xsl:for-each select="$all-items[position() &lt;= $n]">
  <xsl:variable name="p" select="position()"/>
  <div>
    <xsl:copy-of select="$items[position() &gt;= ($p - 1)*5 + 1 and
position() &lt;= $p*5)"/>
  </div>
</xsl:for-each>


Michael Kay
http://www.saxonica.com/


> 
> So the number of groups will in fact depend on the number of <source>
> nodes in the XML file. The <source> nodes will are already in the
> correct order in the XML file so I don't need to sort them in any
> other way in the XSL.
> 
> Cheers,
> Mike.
> 
> 
> On 10/31/05, Wendell Piez <wapiez@xxxxxxxxxxxxxxxx> wrote:
> > Mike,
> >
> > The one thing you don't say is by what rule you would like the
> > splitting to occur (you only say "into two or more groups").
> >
> > If you wanted to split into exactly two groups, you could do:
> >
> > <xsl:template match="sources">
> >    <div>
> >      <xsl:apply-templates
> >        select="source[position() &lt;= (last() div 2)"/>
> >    </div>
> >    <div>
> >      <xsl:apply-templates
> >        select="source[position() &gt; (last() div 2)"/>
> >    </div>
> > </xsl:template>
> >
> > Notice if you have an odd number of source element children, the
> > first group will be short one item.
> >
> > There are other methods available for grouping them differently and
> > even according to data-driven criteria, for example if you need to
> > determine dynamically how many groups you want.

Current Thread