Thomas J.S.: XSLT / Schleife und choose

Beitrag lesen

Hallo,

Die Funktion position() zählt doch aber die Position des Elemetes im XML-File durch.

Schon, aber for-each erzeugt eine Knotenmenge, position() innerhalb von for-each bezieht sich dann nur auf diese Knotenmenge.

Zum Beispiel habe ich drei Hauptkapitel, dann kommen für das dritte Hauptkapitel zwei Unterkapitel, dann würde position() das nächste Hauptkapitel einfach mit 6. nummerieren, obwohl es eigentlich dann das vierte Hauptkapitel wäre.

  1. Kapitel (hautpt)
  2. Kapitel (hautpt)
  3. Kapitel (hautpt)
      3.1. Kapitel (unter)
      3.2. Kapitel (unter)

Ja, das wäre so genau richtig.
So würde ich das gern haben.:o)

Test - XML (ich habe es mehrfach verschachtelt
-------------------------------------------------------------
<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/xsl" href="verennice.xsl"?>
<Handbuch>
 <Handbuchinhalt>
  <Kapitel kapiteltyp="Hauptkapitel">eins</Kapitel>
  <Kapitel kapiteltyp="Hauptkapitel">zwei</Kapitel>
  <Kapitel kapiteltyp="Hauptkapitel">drei
   <Kapitel kapiteltyp="Unterkapitel">drei eins</Kapitel>
   <Kapitel kapiteltyp="Unterkapitel">drei zwei</Kapitel>
  </Kapitel>
  <Kapitel kapiteltyp="Hauptkapitel">vier</Kapitel>
  <Kapitel kapiteltyp="Hauptkapitel">fünf
   <Kapitel kapiteltyp="Unterkapitel">fünf eins</Kapitel>
   <Kapitel kapiteltyp="Unterkapitel">fünf zwei
    <Kapitel kapiteltyp="Unterkapitel">fünf zwei eins</Kapitel>
    <Kapitel kapiteltyp="Unterkapitel">fünf zwei zwei
     <Kapitel kapiteltyp="Unterkapitel">fünf zwei eins eins</Kapitel>
     <Kapitel kapiteltyp="Unterkapitel">fünf zwei eins zwei</Kapitel>
    </Kapitel>
   </Kapitel>
   <Kapitel kapiteltyp="Unterkapitel">fünf drei</Kapitel>
  </Kapitel>
  <Kapitel kapiteltyp="Hauptkapitel">sechs</Kapitel>
  <Kapitel kapiteltyp="Hauptkapitel">sieben</Kapitel>
 </Handbuchinhalt>
</Handbuch>
---------------------------------------------------------

Hast du nur zwei Ebenen (Kap[haupt]/Kap[unter]) reicht folgendes XSL:
---------------------------------------------------------
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
 <html>
  <head>
   <title>kapitel</title>
  </head>
  <body>
   <xsl:apply-templates select="Handbuch/Handbuchinhalt" mode="kapitelzaehler" />
  </body>
 </html>
</xsl:template>
<xsl:template match="Handbuch/Handbuchinhalt" mode="kapitelzaehler">
 <xsl:for-each select="Kapitel">
  <xsl:variable name="pos" select="position()" />
  <xsl:value-of select="concat($pos, '. ', text())" /><br />
  <xsl:if test="Kapitel">
   <xsl:for-each select="Kapitel">
    <xsl:value-of select="concat($pos, '.', position(), '. ', text())" /><br />
   </xsl:for-each>
  </xsl:if>
 </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

-------------------------------------------------------------

Hast du mehr als zwei Ebenen, solltest du sowas benützen (funktioniert natürlich auch bei nur zwei Ebenen):
-------------------------------------------------------------

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
 <html>
  <head>
   <title>kapitel</title>
  </head>
  <body>
   <xsl:apply-templates select="Handbuch/Handbuchinhalt" mode="kapitelzaehler" />
  </body>
 </html>
</xsl:template>
<xsl:template match="Handbuch/Handbuchinhalt" mode="kapitelzaehler">
 <xsl:for-each select="Kapitel">
  <xsl:variable name="pos" select="position()" />
  <xsl:value-of select="concat($pos, '. ', text())" /><br />
  <xsl:if test="Kapitel">
   <xsl:for-each select="Kapitel">
    <xsl:call-template name="zaehler">
     <xsl:with-param name="knoten" select="name()" />
     <xsl:with-param name="pos_eltern" select="$pos" />
    </xsl:call-template>
   </xsl:for-each>
  </xsl:if>
 </xsl:for-each>
</xsl:template>
<xsl:template name="zaehler">
 <xsl:param name="knoten" />
 <xsl:param name="pos_eltern" />
 <xsl:variable name="pos" select="position()" />
 <xsl:value-of select="concat($pos_eltern, '.', $pos, '. ', text())" /><br />
  <xsl:if test="*[name() = $knoten]">
  <xsl:for-each select="*[name() = $knoten]">
   <xsl:call-template name="zaehler">
    <xsl:with-param name="knoten" select="name()" />
    <xsl:with-param name="pos_eltern" select="concat($pos_eltern, '.', $pos)" />
   </xsl:call-template>
  </xsl:for-each>
 </xsl:if>
</xsl:template>
</xsl:stylesheet>

-----------------------------------------------------------------

Das Template "zaehler" kann auch für andere Elemente als Kapitel verwendet werden.

Die Ausgabe vom Test-XML mit dem letzen XSLT:

1. eins
2. zwei
3. drei
3.1. drei eins
3.2. drei zwei
4. vier
5. fünf
5.1. fünf eins
5.2. fünf zwei
5.2.1. fünf zwei eins
5.2.2. fünf zwei zwei
5.2.2.1. fünf zwei zwei eins
5.2.2.2. fünf zwei zwei zwei
5.3. fünf drei
6. sechs
7. sieben

Grüße
Thomas