This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Grouping headers revisted


Hi Jeroen,

> I want to generate a list based on the parameters, so if I have
> param 'discipline' = music and param 'subsdiscipline' = free jazz I
> want to show only the institutions that offer not only music, but
> only free jazz music, so in this particular case 3 institutions will
> be shown. These parameters are optional by the way, so one could
> also select just 'music'.
>
> The thing that makes it more complicated is that I also want to
> group the resulting institutions by city, so the previous example
> would result in:
>
> Amsterdam
>     School of pretentious art
>     School of music
>
> Dendermalsen
>     Dendermalsen School of things

I can think of two approaches that you could take.

First, you could use a two-stage transformation - the first stage
filtering the XML to contain only the institutions that you're
interested in, and the second to group those institutions by city. For
example:

<xsl:key name="institutions" match="institution" use="city" />

<xsl:template match="/">
  <xsl:variable name="matchedInstitutions">
    <xsl:copy-of
      select="country/institutions/institution
                [not($discipline) or
                 disciplines/discipline
                   [@name = $discipline and
                    (not($subdiscipline) or
                     subdiscipline/@name = $subdiscipline)]]" />
  </xsl:variable>
  ...
  <xsl:apply-templates
    select="exsl:node-set($matchedInstitutions)/institution
              [generate-id() =
               generate-id(key('institutions', city)[1])]" />
  ...
</xsl:template>

<xsl:template match="institution">
  ...
  <xsl:for-each select="key('institutions', city)">
    ...
  </xsl:for-each>
  ...
</xsl:template>

In the above the two stages are done within the same stylesheet, using
exsl:node-set() to turn the result of the first stage into a node set
that can be processed during the second stage.

The second approach would be to do the grouping on the whole set and
to filter the result as you go along. Here, you would get the
institutions with unique cities but only process them if there were
any institutions with that city which had the relevant
discipline/subdiscipline combination:

<xsl:template match="country">
  ...
  <xsl:apply-templates
    select="institutions/institution
              [generate-id() =
               generate-id(key('institutions', city)[1])]
              [not($discipline) or
               key('institutions', city)/disciplines/discipline
                 [@name = $discipline and
                  (not($subdiscipline) or
                   subdiscipline/@name = $subdiscipline)]]" />

  ...
</xsl:template>

<xsl:template match="institution">
  ...
  <xsl:for-each
    select="key('institutions', city)
              [not($discipline) or
               disciplines/discipline
                 [@name = $discipline and
                  (not($subdiscipline) or
                   subdiscipline/@name = $subdiscipline)]]">
    ...
  </xsl:for-each>
  ...
</xsl:template>

I hope that helps,

Jeni

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


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]