XSL-Übersicht / xsl:number

xsl:number

xsl:number

xsl:number bietet erweiterte, selektive wie hierarchische Möglichkeiten zur Nummerierung von Elementen.

Auf dieser Seite:

Nehmen Sie ein XML-Dokument, das diesen Aufbau hat:


<ROOT>
  <Einwohner>
   <id>10</id>
   <name>Ruhelos</name>
   <vorname>Rita</vorname>
   <strasse>Hinundweg</strasse>
  </Einwohner>
  <Einwohner>
   <id>3</id>
   <name>Sorglos</name>
   <vorname>Siggi</vorname>
   <strasse>Nixwieweg</strasse>
  </Einwohner>
...
</ROOT>

Selektiv nummerieren mit count

Die folgende Logik gibt alle strasse-Nodes aus. Mit dem count-Attribut sorgt xsl:number dafür, dass nur jene strasse-Nodes nummeriert werden, deren Textinhalt 'Hinundweg' ist.


<xsl:template match="/">
  <Ergebnis>
   <xsl:for-each 
        select="/ROOT/Einwohner">
    <Einwohner>
     <xsl:if 
          test="strasse='Hinundweg'">
      <xsl:attribute name="nr">
       <xsl:number 
            count="Einwohner[strasse='Hinundweg']"/>
      </xsl:attribute>
     </xsl:if>
     <strasse>
      <xsl:value-of 
           select="strasse"/>
     </strasse>
    </Einwohner>
   </xsl:for-each>
  </Ergebnis>
</xsl:template>

Wie versprochen: Die Einwohner in 'Nixwieweg' werden nicht nummeriert.


<Ergebnis>
  <Einwohner nr="1">
   <strasse>Hinundweg</strasse>
  </Einwohner>
  <Einwohner>
   <strasse>Nixwieweg</strasse>
  </Einwohner>
  <Einwohner nr="2">
   <strasse>Hinundweg</strasse>
  </Einwohner>
  <Einwohner nr="3">
   <strasse>Hinundweg</strasse>
  </Einwohner>
  <Einwohner>
   <strasse>Nixwieweg</strasse>
  </Einwohner>
  <Einwohner>
   <strasse>Nixwieweg</strasse>
  </Einwohner>
  <Einwohner nr="4">
   <strasse>Hinundweg</strasse>
  </Einwohner>
  <Einwohner nr="5">
   <strasse>Hinundweg</strasse>
  </Einwohner>
</Ergebnis>

Das format-Attribut unterstützt zudem bei der inidividuellen Formatierung.


<xsl:number count="Einwohner[strasse='Hinundweg']" format="a"/>

Dabei gibt es eine ganze Reihe unterschiedlicher Formatierungsmöglichkeiten.

a a, b, c, d, e
A A, B, C, D, E
i i, ii, iii, iv, v
I I, II, III, IV, V
. .1., .2., .3., ...
w eins, zwei, drei, vier, ...
W EINS, ZWEI, DREI, VIER, ...
Ww Eins, Zwei, Drei, Vier, ...

Jedem Element seine ID

Mitunter stehen Sie vor der Aufgabe, jedem Element in einem XML-Dokument eine ID hinzuzufügen, ohne die restliche Struktur des XML-Dokuments zu verändern. In diesem Fall können Sie so vorgehen:


<xsl:template match="*">
  <xsl:element name="{local-name()}">
    <xsl:attribute name="ID">        
      <xsl:number format="1" count="*" level="multiple"/>
    </xsl:attribute>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:element>
</xsl:template>
<xsl:template match="@*">
  <xsl:attribute name="{local-name()}">
    <xsl:value-of select="."/>
  </xsl:attribute>
</xsl:template>
<xsl:template match="text()">
  <xsl:value-of select="."/>
</xsl:template>

Das Ergebnis sieht dann so aus:


<ROOT ID="1">
  <Einwohner ID="1.1">
   <id ID="1.1.1">10</id>
   <name ID="1.1.2">Ruhelos</name>
   <vorname ID="1.1.3">Rita</vorname>
   <strasse ID="1.1.4">Hinundweg</strasse>
  </Einwohner>
  <Einwohner ID="1.2">
   <id ID="1.2.1">3</id>
   <name ID="1.2.2">Sorglos</name>
   <vorname ID="1.2.3">Siggi</vorname>
   <strasse ID="1.2.4">Nixwieweg</strasse>
  </Einwohner>
</ROOT>

Vgl. .

Hierarchisch nummerieren mit level="multiple"

Sehr hilfreich ist, die hierarchische Struktur ausgewählter Elemente nummerieren zu können. Das geschieht mit level='multiple'.


 <xsl:template match="/">
  <Ergebnis>
   <xsl:for-each 
        select="/ROOT/descendant-or-self::*">
    <element name="{name()}">
     <xsl:attribute name="nr">
       <xsl:number 
            format="a" 
            count="ROOT | Einwohner | strasse" 
            level="multiple"/>
      </xsl:attribute>
    </element>
   </xsl:for-each>
  </Ergebnis>
 </xsl:template>

Damit ergibt sich eine nachvollziehbare Nummerierung.


<Ergebnis>
  <element name="ROOT"      nr="1"/>
  <element name="Einwohner" nr="1.1"/>
  <element name="id"        nr="1.1.1"/>
  <element name="name"      nr="1.1.2"/>
  <element name="vorname"   nr="1.1.3"/>
  <element name="strasse"   nr="1.1.4"/>
  <element name="Einwohner" nr="1.2"/>
  <element name="id"        nr="1.2.1"/>
  <element name="name"      nr="1.2.2"/>
  <element name="vorname"   nr="1.2.3"/>
  <element name="strasse"   nr="1.2.4"/>
  <element name="Einwohner" nr="1.3"/>
  <element name="id"        nr="1.3.1"/>
...
</Ergebnis>

Hierarchische Einzelnummerierung mit level="single"

Ein ähnliches Ergebnis erzielen Sie bei der Arbeit mit level='single'.


<xsl:number 
     format="1" 
     count="*" 
     level="single"/>

Der Unterschied liegt darin, dass die Hierarchiestufen nicht mitgeführt werden.


<Ergebnis>
  <element name="ROOT"      nr="1"/>
  <element name="Einwohner" nr="1"/>
  <element name="id"        nr="1"/>
  <element name="name"      nr="2"/>
  <element name="vorname"   nr="3"/>
  <element name="strasse"   nr="4"/>
  <element name="Einwohner" nr="2"/>
  <element name="id"        nr="1"/>
  <element name="name"      nr="2"/>
  <element name="vorname"   nr="3"/>
  <element name="strasse"   nr="4"/>
  <element name="Einwohner" nr="3"/>
...
</Ergebnis>

Korrekturbedarf bei xsl:sort

Ohne weitere Anweisungen bezieht sich xsl:number auf die ursprüngliche Reihenfolge der Elemente in der Input-Sequenz.


 <xsl:template match="/">
  <Ergebnis>
   <xsl:for-each 
        select="/ROOT/Einwohner">
    <xsl:sort 
         select="strasse"/>
    <element name="{name()}">
     <xsl:attribute name="nr">
      <xsl:number/>
     </xsl:attribute>
    </element>
   </xsl:for-each>
  </Ergebnis>
 </xsl:template>

Wird diese jedoch mit beeinflusst, so ergibt sich ein interpretationsbedürftiges Ergebnis.


<Ergebnis>
  <element name="Einwohner" nr="1"/>
  <element name="Einwohner" nr="3"/>
  <element name="Einwohner" nr="4"/>
  <element name="Einwohner" nr="7"/>
  <element name="Einwohner" nr="8"/>
  <element name="Einwohner" nr="2"/>
  <element name="Einwohner" nr="5"/>
  <element name="Einwohner" nr="6"/>
</Ergebnis>

In diesem Fall hilft der Aufruf der position()-Funktion im Attribut value: Dadurch wird die Nummerierung aus der sortierten Reihenfolge wiedergegeben.


<xsl:number value="position()"/>

wg / 3. Mai 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_number.html