Re: [xsl] grouping content

Subject: Re: [xsl] grouping content
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Fri, 6 Apr 2001 09:27:35 +0100
Hi Gavin,

Other people have shown how to do grouping with your data.  Just to
point out that in:

> In xsl I was thinking of doing this:
> <xsl:choose>
>         <xsl:when test="@Location=$Location">
>         </xsl:when>
>         <xsl:otherwise>
>         <xsl:param name="Location" select="@Location"/>
>         <br/>Location <xsl:value-of select="$Location"/>
>         </xsl:otherwise>
> </xsl:choose>
> <br/><xs:value-of select="@Value"/>
> For some reason it will go straight to the otherwise and not even
> look at the test. So I get this:

I think you're trying to do some kind of updating of the $Location
variable with each step.  One of the important lessons to learn about
XSLT is that variables and parameters in XSLT cannot be changed once
they're set.

However, you could create a recursive template with the same kind of
logic as you have in the above.  You could step through the Location
elements one by one, passing in the Area of one Location when you
apply templates to the next:

<xsl:template match="Location">
   <xsl:param name="Location" select="@Area" />
   <xsl:if test="@Area != $Location">
      <br />Location <xsl:value-of select="@Area" />
   <br /><xsl:value-of select="@Value" />
   <!-- apply templates to the next Location element, this time with
        the $Location parameter set to the (new) @Area -->
   <xsl:apply-templates select="following-sibling::Location[1]">
      <xsl:with-param name="Location" select="@Area" />

To start the process, you have to apply templates to the first
Location element *only*:

   <xsl:apply-templates select="Location[1]" />

However, the usual method in XSLT is to apply templates to everything,
and try to work out what to do given the information you have about
the one thing you're processing at the moment. In this case, you would
have a single template for a Location element. Each Location element
can work out whether to add a Location heading by checking its
immediately preceding sibling Location's Area attribute - if it's
different from this one, then you need to add the Location heading:

<xsl:template match="Location">
   <xsl:if test="@Area != preceding-sibling::Location[1]/@Area">
      <br />Location <xsl:value-of select="@Area" />
   <br /><xsl:value-of select="@Value" />

Note that these solutions *only* work because you've already got the
Location elements sorted in order.  The other solutions you've been
given, using the Muenchian Method, work whatever the order of the
Location elements.

I hope that helps,


Jeni Tennison

 XSL-List info and archive:

Current Thread