Re: [xsl] How to do Control Break?

Subject: Re: [xsl] How to do Control Break?
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Mon, 1 Jul 2002 10:29:19 +0100
Hi Jonathan,

> I've read about the Muenchian method of grouping but the examples
> are all about outputting something different when the group changes
> but not continuing it on per entity of the group.

Let's get the logic right first; this is a bit easier to do with the
XSLT 2.0 method of grouping because we don't have to worry about all
the keys and things from the Muenchian Method.

You want to group the z:row elements by FirstName and Surname. In XSLT
2.0, you can do the grouping with xsl:for-each-group:

  <xsl:for-each-group select="z:row"
                      group-by="concat(@Surname, ', ', @FirstName)">
    ...
  </xsl:for-each-group>

[Does anyone else think that it would be neater to follow the xsl:sort
method for grouping by two things at once -- having two xsl:group
elements rather than having to use concat() to create the grouping
key, especially given that these values are likely typed?]
  
Inside this xsl:for-each-group, the current node list holds the first
z:rows with each unique combination of Surname and FirstName. The
first will be the z:row with the name "Adam Awad", the second the
z:row with the name "Adam Hutchinson", the third "Adam Ryan". At this
level you can decide on the color of the row based on the position of
the current node within the current node list (the position()
function) -- if it's odd it should be #E3EEFB, if it's even it should
be #D0E3F8. You can store this colour in a variable:

  <xsl:for-each-group select="z:row"
                      group-by="concat(@Surname, ', ', @FirstName)">
    <xsl:variable name="color"
                  select="if (position() mod 2 = 1)
                          then '#E3EEFB'
                          else '#D0E3F8'" />
    ...
  </xsl:for-each-group>

Then you can cycle through the members of each group to create the
rows, using the value of the $color variable as the value of the color
attribute, as follows:

  <xsl:for-each-group select="z:row"
                      group-by="concat(@Surname, ', ', @FirstName)">
    <xsl:variable name="color"
                  select="if (position() mod 2 = 1)
                          then '#E3EEFB'
                          else '#D0E3F8'" />
    <xsl:for-each select="current-group()">
      <tr color="{$color}">
        ...
      </tr>
    </xsl:for-each>
  </xsl:for-each-group>

The Muenchian Method way has just the same logic, it's just that
identifying the unique z:rows and the members of that group involves
using a key, and of course you have to use the XSLT 1.0 syntax. The
key in this case is something like:

<xsl:key name="rows" match="z:row"
         use="concat(@Surname, ', ', @FirstName)" />

And the code looks something like:

  <xsl:for-each
    select="z:row[count(.|key('rows',
                              concat(@Surname, ', ', @FirstName))[1])
                  = 1]">
    <xsl:variable name="color">
      <xsl:choose>
        <xsl:when test="position() mod 2 = 1">#E3EEFB</xsl:when>
        <xsl:otherwise>#D0E3F8</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:for-each select="key('rows',
                              concat(@Surname, ', ', @FirstName)">
      <tr color="{$color}">
        ...
      </tr>
    </xsl:for-each>
  </xsl:for-each-group>

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread