Gruppierung mit xsl:for-each-group

(Auszug aus "XSLT 2.0 & XPath 2.0" von Frank Bongers, Kapitel 2.)

Die Gruppierung von Inhalten war mit XSLT 1.0 eine aufwendig zu lösende und umständliche Angelegenheit. Durch Steve Muench von Oracle wurde hierzu seinerzeit ein komplexer, auf der Erstellung von Schlüsselwerten (keys) basierender Ansatz entwickelt, der ihm zu Ehren als Muenchsche Methode in die Geschichte von XSLT einging.

Die Notwendigkeit, für Gruppierungen die Muenchsche Methode anzuwen­den, ist in XSLT 2.0 nicht mehr gegeben. Diese Lösung würde allerdings nach wie vor funktionieren. XSLT 2.0 führt zwecks Erleichterung des Gruppierens eine eigene Instruktion ein: xsl:for-each-group.

Die Instruktion bildet grundsätzlich, vergleichbar mit xsl:for-each, eine Schleife, jedoch nicht über Items einer Sequenz, sondern über Gruppen von Items. Grundlage ist auch hier eine Eingabesequenz, die anhand des select-Attributs der Instruktion gebildet wird.

Zusätzlich wird ein Gruppierungskritierium durch das group-by-Attribut (oder vergleichbare Attribute) übergeben, anhand dessen die Items der Sequenz in die Gruppen zusammengefasst werden, über die anschließend die Schleife gebildet wird. Für jeden unterscheidbaren Wert des Gruppierungskri­teriums wird eine eigene Gruppe begonnen; leere Gruppen kann es dabei per Definition nicht geben:

<xsl:for-each-group select="sequenz" group-by="kriterium">
  <!-- Ausgabe -->
</xsl:for-each-group>

Auf die Sequenz der Items der aktuellen Gruppe kann während ihres Schleifen­durchlaufs mit der Funktion current-group() zugegriffen werden. Diese kann wie jede normale Sequenz verarbeitet werden. Das zum gleichen Zeitpunkt gültige Gruppierungskriterium kann mittels current-grouping-key() abgefragt werden.

Der Buchkatalog nach Verlagen gruppiert

Es ist nun relativ leicht, die Buchliste nach Verlagen zu gruppieren. Der aktuelle Verlag kann mittels der XSLT-Funktion current-grouping-key() ausgegeben werden. Von den dazugehörigen Büchern wird jeweils nur der Titel ausgegeben, indem auf die von current-group() zurückgegebene Sequenz ein Pfadausdruck angewendet wird. Die Ausgabe der Gruppensequenz erfolgt gemeinsam über xsl:value-of:

<xsl:for-each-group select="buchhandel/buch" group-by="buchverlag">
  <p><b><xsl:value-of select="current-grouping-key()"/></b><br/><xsl:value-of select="current-group()/buchtitel" separator=", "/></p>
</xsl:for-each-group>

Die Gruppierung gelingt ohne Weiteres. Nur die Ausgabe der Buchtitel wirkt noch nicht sonderlich inspirierend, was aber gleich behoben sein wird:

Touchstone
Where Wizards Stay Up Late

Spacetrotter Publishing
Yet Another Hitchhiker's Guide to the Galaxy, Hitchhiker's Guide to the Galaxy, Another Hitchhiker's Guide to the Galaxy

etc.

Die Verlagsgruppen werden nach erstem Erscheinen des jeweiligen Verlags ausgegeben (order of first appearence). Analog zu xsl:for-each bietet auch xsl:for-each-group die Möglichkeit einer Sortierung durch xsl:sort:

<xsl:for-each-group select="buchhandel/buch" group-by="buchverlag">
  <xsl:sort select="buchverlag"/>
  <p><b><xsl:value-of select="current-grouping-key()"/></b><br/><xsl:value-of select="current-group()/buchtitel" separator=", "/></p>
</xsl:for-each-group>

xsl:for-each innerhalb von xsl:for-each-group

Nachdem die gruppierte Liste nach Verlagen geordnet ausgegeben wird, kann auch die Ausgabe der Titel etwas sauberer erfolgen. Da current-group() eine Sequenz zurückgibt, kann diese genauso gut durch xsl:for-each verarbeitet werden, anstatt durch xsl:value-of unmittelbar ausgegeben zu werden:

<xsl:for-each-group select="buchhandel/buch" group-by="buchverlag">
  <xsl:sort select="buchverlag"/>
  <p>
    <b><xsl:value-of select="current-grouping-key()"/></b><br/>
    <ul>
      <xsl:for-each select="current-group()/buchtitel">
        <li><xsl:value-of select="."/></li>
      </xsl:for-each>
    </ul>
  </p>
</xsl:for-each-group>

xsl:for-each-group innerhalb von xsl:for-each-group

Innerhalb von Gruppen kann wiederum gruppiert werden. Hier erfolgt eine erneute Gruppierung nach Autoren innerhalb der äußeren xsl-for-each-group-Instruktion. Hierfür werden zwei derartige Instruktionen einfach ineinander ver­schachtelt:

...
<xsl:for-each-group select="buchhandel/buch" group-by="buchverlag">
  <xsl:sort select="buchverlag"/>
  <p><b><xsl:value-of select="current-grouping-key()"/></b></p>
  <xsl:for-each-group select="current-group()" group-by="buchautor">
    <xsl:sort select="buchautor[1]"/>
    <p><i><xsl:value-of select="current-grouping-key()"/></i></p>
    <ul>
      <xsl:for-each select="current-group()">
        <xsl:sort select="buchtitel"/>
        <li><xsl:value-of select="buchtitel"/></li>
      </xsl:for-each>
    </ul>
  </xsl:for-each-group>
</xsl:for-each-group>
...

In jeder der beiden Gruppierungsschleifen erfolgt eine Sortierung durch xsl:sort. Die innere xsl:for-each-group-Instruktion arbeitet mit der Cur­rent Group der äußeren und gruppiert diese jeweils nach den Buchautor-Ele­menten. Im Inneren dieser Schleife wechselt Current Group und auch der Current Grouping Key. Die Current Group der inneren Schleife dient als Eingabe­sequenz einer xsl:for-each-Instruktion, die, nach erneuter Sortie­rung, die Buchtitel ausgibt.

Auf diesem Wege wird eine zweifache Gruppierung erreicht: zunächst nach Verlagen und innerhalb der Verlage nach Autoren, deren Buchtitel jeweils alphabetisch geordnet ausgegeben werden.

   

<< zurück vor >>
Tipp der data2type-Redaktion:
Zum Thema XSLT bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © Galileo Press, Bonn 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XSLT 2.0 & XPath 2.0 ― Das umfassende Handbuch" denselben Bestimmungen wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Galileo Press, Rheinwerkallee 4, 53227 Bonn