XPath 3.0, XPath 2.0, XPath 1.0 / XPath-Funktionen / XPath: Sequenz-Funktionen / Gruppieren in XPath 1.0/XSL 1.0

Gruppieren in XPath 1.0/XSL 1.0

Gruppieren in XPath 1.0/XSL 1.0

➪ Die Zusammenfassung mehrfach auftretender Werte ist eine häufige Aufgabe auch in XSLT 1.0/XPath 1.0. Wenn die Systemkonfiguration den Einsatz spezieller XSL-Prozessoren erzwingt, die nicht über geeignete Extensions verfügen, bleibt die Suche nach geeigneten Konzepten.

Auf dieser Seite:

Alternativ zu , und LINQ können Sie auch in XSLT 1.0/XPath 1.0 mehrfach auftretende Werte gruppieren. Drei verschiedene konzeptionelle Ansätze möchte ich hier vergleichen. Als Grundlage habe ich eine XML-Testdatei (1 GB Dateigröße, 30 Mio Nodes Kauf/artikel) mit diesem Aufbau verwendet:


<root>
  <Kauf><artikel>Hemd</artikel></Kauf>
  <Kauf><artikel>Hose</artikel></Kauf>
  <Kauf><artikel>Schuhe</artikel></Kauf>
  <Kauf><artikel>Hemd</artikel></Kauf>
  <Kauf><artikel>Hose</artikel></Kauf>
  <Kauf><artikel>Schuhe</artikel></Kauf>
  <!-- weitere Nodes -->
</root>

Das Ergebnis soll jeweils lauten:


<ergebnis>
  <artikel name="Hemd"/>
  <artikel name="Hose"/>
  <artikel name="Schuhe"/>
</ergebnis>

Arbeiten mit not und following::

Der erste Ansatz beruht (ähnlich wie bei der -Berechnung in XSLT 1.0) auf der Verwendung der XPath-Pfade oder , verbunden mit der not-Funktion. Verglichen mit den beiden Alternativen finde ich diesen Ansatz überschaubarer und leichter zu warten. Die Belastung des Arbeitsspeichers lag mit dem eingesetzten Prozessor bei 1906 MB. Freilich dauerte die Verarbeitung der Testdatei 34 Sekunden.


<xsl:for-each select="//Kauf[not
                     (artikel/text()=following::Kauf/artikel/text())
                     ]">
    <artikel name="{artikel}"/>
</xsl:for-each>

Arbeiten mit generate-id()

Der zweite Ansatz arbeitet mit sowie mit . Die Belastung des Arbeitsspeichers lag mit dem eingesetzten Prozessor bei 2915 MB. Die höhere Speicherbelastung führe ich auf die Verwendung von xsl:key zurück. Die Verarbeitung der Testdatei war mit ca. 10 Sekunden deutlich schneller.


<xsl:key name="ka" match="//Kauf" use="artikel"/>
<xsl:for-each 
     select="//Kauf[generate-id() = generate-id(key('ka', artikel)[1])]">
    <artikel name="{artikel}"/>
</xsl:for-each>

Das wird nachvollziehbar, wenn Sie berücksichtigen, dass die folgenden Aufrufe jeweils dasselbe Ergebnis haben (in meinem System d1e33).


<xsl:value-of select="generate-id(key('ka', 'Hemd'))"/>
<xsl:value-of select="generate-id(//Kauf[artikel = 'Hemd'])"/>

Die Muench'sche Methode

Der dritte Ansatz ist auch bekannt als Muench'sche Methode. Hier kommt ebenfalls zum Einsatz, wodurch die Belastung des Arbeitsspeichers bei 2929 MB lag. Die Verarbeitung der Testdatei war mit 4 Sekunden am schnellsten.


<xsl:key name="ka" match="//Kauf" use="artikel"/>
<xsl:for-each select="//Kauf[count(. | key('ka', artikel)[1])=1]">
    <artikel name="{artikel}"/>
</xsl:for-each>

wg / 13. Mai 2018



Fragen? Anmerkungen? Tipps?

Bitte nehmen Sie Kontakt zu mir auf.






Vielen Dank für Ihr Interesse an meiner Arbeit.


V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de

www.wilfried-grupe.de/XPath_10_gruppieren.html