XSL - Übersicht / xsl:accumulator

xsl:accumulator

xsl:accumulator

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

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, 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", einer 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. So ist es 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>

wg / 29. Dezember 2017



Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf:

Vorname
Nachname
Mailadresse







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: info2018@wilfried-grupe.de

www.wilfried-grupe.de/xsl_accumulator.html