XSL / Die XSLT - Struktur / xsl:accumulator
![]() |
![]() |
➪ xsl:accumulator bietet leistungsfähige Unterstützung bei der Implementierung globaler Counter.
Siehe xsl:accumulator.
In zahlreichen herkömmlichen Programmiersprachen ist die Counterimplementierung eine einfache Sache.
int x = 0;
for(int y=0; y<10; y++) x = x + 1;
Leider nicht in XSL/XPath 1.0 und 2.0: Hier sind zur Implementierung globaler Counter teilweise umständliche Logiken erforderlich, wie die Arbeit mit der position()-Funktion, Variablen, rekursive Template-Aufrufe oder nicht-standardkonforme, prozessorabhängige Zusatzfeatures.
In XSLT 3.0 löst xsl:accumulator dieses Problem auf eine elegante Weise. Der folgende Ansatz definiert einen xsl:accumulator mit dem Namen increment, einem Startwert von "0" sowie einer internen Logik, die bei jedem Auftreten eines Elements Mensch im Quelldokument den Startwert um 1 erhöht.
<xsl:accumulator
name="increment"
initial-value="0"
as="xs:integer">
<xsl:accumulator-rule
match="Mensch"
select="$value + 1"/>
</xsl:accumulator>
Aufrufbar wird dieser xsl:accumulator durch ein herkömmliches Template, das bei jedem treffenden Element Mensch über die Funktion accumulator-after('increment') dessen Wert ausgibt.
<xsl:template match="/">
<ergebnis>
<xsl:for-each select="//Mensch">
<Person VN="{vorname}" NN="{name}">
<xsl:value-of select="accumulator-after('increment')"/>
</Person>
</xsl:for-each>
<Endstand>
<xsl:value-of select="accumulator-after('increment')"/>
</Endstand>
</ergebnis>
</xsl:template>
Das Ergebnis spricht für sich:
<ergebnis>
<Person VN="Hugo" NN="Holzflos">1</Person>
<Person VN="Nicole" NN="Nixlos">2</Person>
<Person VN="Stefan" NN="Sprachlos">3</Person>
<Person VN="Stefan" NN="Sagblos">4</Person>
<Person VN="Siggi" NN="Sorglos">5</Person>
<Person VN="Heini" NN="Herzlos">6</Person>
<Person VN="Rudi" NN="Rhodos">7</Person>
<Person VN="Karl" NN="Kolos">8</Person>
<Person VN="Simone" NN="Sinnlos">9</Person>
<Person VN="Horst" NN="Hirnlos">10</Person>
<Person VN="Werner" NN="Wertlos">11</Person>
<Person VN="Ludwig" NN="Lustlos">12</Person>
<Person VN="Willi" NN="Wasistlos">13</Person>
<Person VN="Rita" NN="Ruhelos">14</Person>
<Person VN="Susi" NN="Schlaflos">15</Person>
<Person VN="Lotte" NN="Rielos">16</Person>
<Person VN="Betty" NN="Bodenlos">17</Person>
<Person VN="Martin" NN="Muehelos">18</Person>
<Person VN="Liane" NN="Leinenlos">19</Person>
<Endstand>19</Endstand>
</ergebnis>
Aber xsl:accumulator kann noch mehr. Es ist möglich, durch den gezielten Einsatz von xsl:accumulator-rule den aktuellen Counterwert gezielt zu verändern. So wird bei dem folgenden xsl:accumulator der Wert auf 0 zurückgesetzt, wenn Ort/id ohne Rest durch 3 teilbar ist, im anderen Fall aber verdoppelt.
<xsl:accumulator
name="increment"
initial-value="0"
as="xs:integer">
<xsl:accumulator-rule
match="Ort[id mod 3 != 0]"
select="$value * 2"/>
<xsl:accumulator-rule
match="Ort[id mod 3 = 0]"
select="0"/>
<xsl:accumulator-rule
match="Mensch"
select="$value + 1"/>
</xsl:accumulator>
Aufgerufen wird dieser modifizierte xsl:accumulator wie üblich durch ein xsl:template.
<xsl:template match="/">
<ergebnis>
<xsl:for-each select="//Ort">
<Stadt>
<posb>
<xsl:value-of
select="accumulator-before('increment')"/>
</posb>
<xsl:for-each select="Mensch">
<Person VN="{vorname}" NN="{name}">
<xsl:value-of
select="accumulator-after('increment')"/>
</Person>
</xsl:for-each>
</Stadt>
</xsl:for-each>
<Endstand>
<xsl:value-of select="accumulator-after('increment')"/>
</Endstand>
</ergebnis>
</xsl:template>
Und das Ergebnis erklärt sich dann von selbst:
<ergebnis>
<Stadt>
<posb>0</posb>
<Person VN="Hugo" NN="Holzflos">1</Person>
<Person VN="Nicole" NN="Nixlos">2</Person>
<Person VN="Stefan" NN="Sprachlos">3</Person>
<Person VN="Stefan" NN="Sagblos">4</Person>
<Person VN="Siggi" NN="Sorglos">5</Person>
<Person VN="Heini" NN="Herzlos">6</Person>
</Stadt>
<Stadt>
<posb>12</posb>
<Person VN="Rudi" NN="Rhodos">13</Person>
<Person VN="Karl" NN="Kolos">14</Person>
<Person VN="Simone" NN="Sinnlos">15</Person>
<Person VN="Horst" NN="Hirnlos">16</Person>
<Person VN="Werner" NN="Wertlos">17</Person>
<Person VN="Ludwig" NN="Lustlos">18</Person>
</Stadt>
<Stadt>
<posb>0</posb>
<Person VN="Willi" NN="Wasistlos">1</Person>
<Person VN="Rita" NN="Ruhelos">2</Person>
<Person VN="Susi" NN="Schlaflos">3</Person>
<Person VN="Lotte" NN="Rielos">4</Person>
<Person VN="Betty" NN="Bodenlos">5</Person>
<Person VN="Martin" NN="Muehelos">6</Person>
<Person VN="Liane" NN="Leinenlos">7</Person>
</Stadt>
<Endstand>7</Endstand>
</ergebnis>
<xsl:accumulator
name = eqname
initial-value = expression
as? = sequence-type
streamable? = boolean >
<!-- Content: xsl:accumulator-rule+ -->
</xsl:accumulator>
<xsl:accumulator-rule
match = pattern
phase? = "start" | "end"
select? = expression >
<!-- Content: sequence-constructor -->
</xsl:accumulator-rule>
Siehe auch
fn:accumulator-before($name as xs:string) as item()*
fn:accumulator-after($name as xs:string) as item()*
wg / 24. September 2020
Fragen? Anmerkungen? Tipps?
Bitte nehmen Sie Kontakt zu mir auf.
V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn
☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de