XSL-Übersicht / xsl:accumulator

xsl:accumulator

xsl:accumulator

xsl:accumulator bietet leistungsfähige Unterstützung bei der Implementierung globaler Counter.

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 -Funktion, , 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 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>

wg / 5. April 2018



Fragen? Anmerkungen? Tips?

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/xsl_accumulator.html