XSLT: Templates


... [ Seminar XML und Haskell ] ... [ XSLT ] ... [ Anweisungen ] ...

Übersicht: Templates


Verarbeitung eines Quelldokuments

Das Quelldokument wird knotenweise abgearbeitet. Die Verarbeitung beginnt dabei mit dem Wurzelknoten ("/"). Für diesen Knoten wird eine Regel im Stylesheet gesucht, die die weitere Vorgehensweise bestimmt.

Eine Regel ("Template") ist wie folgt als Toplevel-Element deklariert:

  <xsl:template match="doc" priority="1" name="wurzel" mode="mode1">
    <html>
      <head>
      </head>

      <body>
      </body>
    </html>
  </xsl:template>

Das match-Attribut legt dabei fest, auf welche Knoten die Regel paßt.
Der gesamte Inhalt des passenden Templates wird dann ins Zieldokument eingefügt.

Nach oben

Anwenden weiterer Templates

Im Bild oben ist zu erkennen, daß nur die Regel für das "doc"-Element angewendet wurde (es sind keine table-Elemente im Zieldokument vorhanden).
Will man auch die untergeordneten Elemente verarbeiten, muß das durch eine apply-templates-Anweisung veranlaßt werden:

  <xsl:template match="doc" priority="1" name="wurzel" mode="mode1">
    <html>
      <head>
      </head>

      <body>
        <xsl:apply-templates select="*" mode="mode2"/>
      </body>
    </html>
  </xsl:template>

Für Knoten, die dem Muster im select-Attribut entsprechen (Default: *) werden dann die passenden Templates gesucht und deren Inhalt anstelle des apply-templates-Elements ins Zieldokument eingefügt:

Zusätzlich kann das mode-Attribut angeben, daß nur Templates mit genau diesem mode-Attribut verwendet werden sollen. Der Wert kann frei definiert werden.
So kann genau angegeben werden, wann wo welche Knoten verarbeitet werden.

Nach oben

Default-Templates

Wird für ein Element keine passende Regel gefunden, so treten im Prozessor eingebaute "Default-Templates" in Kraft:

  <xsl:template match="*|/">
    <xsl:apply-templates>
  </xsl:template>

  <xsl:template match="@*|text()">
    <xsl:value-of select=".">
  </xsl:template>

  <xsl:template match="comment()|processing-instruction()"/>

Bei Elementknoten ohne passende Regel werden also mit deren Kindknoten fortgefahren; Texte und Attribute werden mittels value-of (wird später erklärt) durch ihren Wert ersetzt; Kommentare und PIs werden ignoriert.

Nach oben

Konfliktbehandlung

Sowohl bei den am Anfang vorgestellten space-Elementen als auch bei template-Elementen kann es passieren, daß zwei verschiedene Muster auf denselben Knoten passen. Ein Beispiel:

  <xsl:strip-space elements="*"/>
  <xsl:preserve-space elements="html"/>

In diesem Fall wäre nicht klar, ob ein html-Element Leere Textknoten beibehalten oder entfernt werden sollen.
Die Lösung dieses Konflikts erfolgt in drei Schritten:

  1. Konfliktierende Elemente mit höherer Import-Priorität (d. h. aus später importierten Stylesheets) erhalten den Vorzug.
  2. xsl:template-Elemente mit einem höheren Wert des priority-Attributs erhalten den Vorzug.
  3. Genauere Muster werden bevorzugt:
  4. Führen die Schritte 1 und 2 nicht zu einem eindeutigen Element, so ist dies ein Fehler. Der XSLT-Prozessor hat aber dann die Möglichkeit, das zuletzt deklarierte Element anzuwenden (dies widerspricht aber der Aussage, daß die Reihenfolge keine Rolle spielt).

In unserem Beispiel würden leere Textknoten in html-Elementen erhalten bleiben, da das Muster "*" die Priorität -0.25, das Muster "html" jedoch die Priorität 0 hat.

Nach oben

Direktes Aufrufen von Templates

Zusätzlich zum impliziten Aufruf von Templates mittels apply-templates können Templates auch explizit über ihren Namen (name-Attribut) aufgerufen werden:

  <xsl:template name="tmpl1">
    ...
  </xsl:template>

  <xsl:template match="*">
    <tag>
      <xsl:call-template name="tmpl1"/>
    </tag>
  </xsl:template>

Der Wert eines eventuell vorhandenen match-Attributs spielt hierbei keine Rolle.

Nach oben

Variablen und Parameter

Es ist auch möglich, Variablen zu deklarieren und dem aufgerufenen Template Parameter zu übergeben.
Diese können dann innerhalb von XPath-Ausdrücken verwendet werden.

  <xsl:variable name="x" select="0815"/>

  <xsl:template name="tmpl1">
    <xsl:variable name="x">2</xsl:variable>
    <xsl:param name="y" select="3"/>
    
    <xsl:apply-templates select="*[$x]"/>
  </xsl:template>

  <xsl:template match="*">
    <tag>
      <xsl:call-template name="tmpl1">
        <xsl:with-param name="y" select="1"/>
      </xsl:call-template>
    </tag>
  </xsl:template>

In diesem Fall existiert eine globale Variable x mit dem Wert 0815, das erste Template hat eine lokale Variable x mit dem Wert 2 und einen Parameter y mit dem Standardwert 3.
Der einzige Unterschied zwischen Variablen und Parametern ist, daß Parameterwerte beim Aufruf mittels with-param überschrieben werden können (y hat in diesem Beispiel dann den Wert 1). Ansonsten verhalten sich Variablen und Parameter identisch; es dürfen in einem Template auch nicht Variablen und Parameter mit gleichem Namen auftreten.
Lokale Variablen haben jedoch Vorrang vor globalen; die lokale Variable x "versteckt" hier die globale Variable x.

Der Ausdruck "Variable" ist auch nicht ganz korrekt, denn da XSLT in diesem Sinne eine funktionale Programmiersprache darstellt, kann man den Wert einer Variable oder eines Parameters nach der Initialisierung nicht mehr ändern.

Nach oben

... [ Seminar XML und Haskell ] ... [ XSLT ] ... [ Anweisungen ] ...