next up previous contents
Nächste Seite: 3.5 Funktionen Aufwärts: 3 XSLT Vorherige Seite: 3.3 Grundlagen   Inhalt


3.4 Datenabhängige Verarbeitung

Nicht jeder Knoten des Ausgangsdokumentes soll einfach übernommen werden. Es sollen nur solche mit bestimmten Eigenschaften, Zusammenfassungen in Form der Anzahl des Auftretens oder die Ergebnisse von Berechnungen kombinierter Werte in den Ergebnisbaum eingetragen werden. Wurde ein ausgewählter Knoten zum aktuellen Kontext gemacht, so werden auf ihn Regeln bezüglich seiner Weiterverarbeitung angesetzt. Hierbei lassen sich Entscheidungen mittels if-Abfragen bei nur einem Test, oder choose bei mehreren Überprüfungen vornehmen. Damit lassen sich Verzweigungen in Abhängigkeit vom Eingangsdokument realisieren. Bei if-Anweisungen muss anhand des test-Attributes, das einen Wahrheitsausdruck, also true oder false, enthalten muss, eine Auswertung vorgenommen werden. Diese Auswertung entscheidet darüber, ob die weiteren Arbeitsschritte innerhalb des Elementes überhaupt durchgeführt werden sollen. Es steht keine else-Abfrage zur Verfügung, wie das in gängigen Programmiersprachen der Fall ist. Dafür verwendet man die Wahlmöglichkeit mittels des choose-Elementes. Innerhalb dieses Elementes lassen sich ein bis beliebig viele when-Abfragen einfügen, die ebenso wie die if-Abfrage mittels eines test-Attributes festlegen lassen, ob ihr Inhalt ausgeführt werden soll. Vergleichbar mit switch-case-Konstrukten in anderen Sprachen, lässt sich auch innerhalb von choose ein otherwise-Fall definieren, der immer dann zum Einsatz kommt, wenn keiner der zuvor in den when-Tests abgefragten Fälle mit true ausgewertet wurde.

Beispiel 3.4.1:
Wenn der Knoten des aktuellen Kontextes sich an erster Position befindet, wird erstens ausgegeben, ist er der letzte unter seinen Geschwistern der gleichen Ebene, so liefert diese Abfrage letztens. Sollte keiner dieser beiden Fälle zutreffen, so wird nächstens in den Ergebnisbaum eingefügt.
<xsl:choose>
  <xsl:when test="position()=1">
    <xsl:text>erstens</xsl:text>
  </xsl:when>
  <xsl:when test="last()">
    <xsl:text>letztens</xsl:text>
  </xsl:when>
  <xsl:otherwise>
    <xsl:text>nächstens</xsl:text>
  </xsl:otherwise>
</xsl:choose>
Während sich Verzweigungen in XSLT nicht wesentlich von gängigen Programmiersprachen unterscheiden, so gibt es allerdings keine abzählbaren Schleifen, wie beispielsweise while oder for-Schleifen. Das for-each-Element erfüllt einen etwas anderen Zweck. Es ist abhängig davon wie häufig das Eingangsdokument durchlaufen wird. So lässt sich bei ihm über ein select-Attribut ein XPath-Ausdruck angeben, der dafür sorgt, dass der gesamte Inhalt des for-each auf jedes Element angewendet wird, das mittels des Ausdruckes erreicht wird. Es ist hierbei zu beachten, dass das Element, auf den der Inhalt angewendet wird, zu dem aktuellen Kontext während der Verarbeitung wird.

Beispiel 3.4.2:
Innerhalb des aktuellen Kontextes soll für jeden test-Knoten der Wert seines wert-Knotens ausgegeben werden.
<xsl:for-each select="test">
  <xsl:value-of select="wert"/>
</xsl:for-each>
Es existieren auch Variablen in XSLT, doch lassen sich diese nur einmal initialisieren und nicht wieder verändern. In ihnen können Werte, Knoten oder auch gesamte Bäume gespeichert werden. Das variable-Element kann entweder über das select-Attribut den Wert der Variablen zuweisen oder über seinen Inhalt. Der Name hierfür wird mittels des name-Attributes angegeben. Die Sichtbarkeit einer Variablen beschränkt sich auf das Element, in dem sie erzeugt wurde. Globale Variablen sind demnach nur solche, die unterhalb des stylesheet-Elementes definiert wurden. Alle anderen sind lokale Variablen innerhalb des jeweiligen Kontextes. Auf Variablen kann innerhalb ihrer Sichtbarkeit durch die Verknüpfung des Dollarzeichens $ mit dem Variablennamen innerhalb von anderen select- oder test-Attributen zugegriffen werden. Zur Ausgabe des gespeicherten Wertes in dem Ergebnisbaum dient beispielsweise die Kombination des value-of-Elementes mit dem select-Attribut, das den Wert der Variablen an der entsprechenden Stelle einfügt.

Beispiel 3.4.3:
Eine Variable namens var mit dem Inhalt des aktuellen Kontextknotens lässt sich auf zwei Arten erzeugen:
  1. <xsl:variable name="var">
      <xsl:value-of select="."/>
    </xsl:variable>
    
  2. <xsl:variable name="var" select"."/>
    
Der Zugriff auf den Wert der Variablen ist immer gleich. In diesem Beispiel wird der Wert einfach ausgegeben:
<xsl:value-of select="$var"/>
Bei einer einfachen Abfrage, wie in dem obigen Beispiel, unterscheidet sich die Art der Definition einer Variablen nicht. Doch die kurze Schreibweise kommt schnell an ihre Grenzen. So lassen sich innerhalb des select-Attributes keine anderen XSLT-Elemente aufrufen und ihr Rückgabewert speichern. Das lässt sich nur im Inhalt des variable-Elementes durchführen. Um innerhalb der Verarbeitung eines Elementes, die Verarbeitung anderer Elemente, beispielsweise seiner Kinder, anzustoßen, und damit die Reihenfolge der Verarbeitung innerhalb des Baumes zu bestimmen, wird das apply-templates-Element benutzt. Diesem Element läßt sich optional mittels select- Attribut mitteilen, welche Knoten als nächstes zu behandeln sind. Die dementsprechenden Vorlagen werden dann an dieser Stelle aufgerufen. Um unterschiedliche Vorlagen für gleiche Knoten nur an verschiedenen Stellen in der Verarbeitung zu ermöglichen, können den Vorlagen mittels des mode-Attributes verschiedene Modi zugewiesen werden. Diese Modi können bei dem Aufruf einer Vorlage mittels apply-templates als mode-Attribut angegeben werden. Damit lassen sich verschiedenartige Behandlungen der Knoten zu unterschiedlichen Bearbeitungszeitpunkten festlegen. Eine andere Möglichkeit Vorlagen aufzurufen ist mit dem Element call-template gegeben. Damit lassen sich mit Namen versehene Vorlagen bearbeiten. Dazu ist der Vorlage ein Name durch das name-Attribut mitzugeben. Über den Namen ist die Vorlage eindeutig identifizierbar und über die Angabe im name-Attribut des aufrufenden Elements wird sie an der aufrufenden Position bearbeitet. So können auch Vorlagen erstellt werden, die unabhängig vom selektierten Knoten aufgerufen werden können und deren aktueller Kontext sich somit nicht ändert.

Beispiel 3.4.4:
Innerhalb der Vorlage, die auf die Wurzel des Dokumentes angewendet wird, wird die Vorlage mit Namen info aufgerufen. Dieser Aufruf kann an beliebigen Stellen mit anderen Vorlagen wiederholt werden und alle Verarbeitungsanweisungen, die in ihr definiert werden, brauchen nur an einer Stelle festgeschrieben werden.
<xsl:template match="/">
  <xsl:call-template name="info"/>
</xsl:template>

<xsl:template name="info">
  <xsl:text>Hier Infos einfügen!</xsl:text>
</xsl:template>
Einige wichtige Aufgaben lassen sich allerdings erst durch das Hinzufügen von Parametern realisieren. So können Vorlagen erzeugt werden, die Parameter benutzen, indem ein param-Element direkt am Anfang der Vorlage definiert wird. Innerhalb der Vorlage kann auf diesen Parameter dann wie auf eine Variable zugegriffen werden. Zur Übergabe eines Wertes an den Parameter, wird beim Aufruf der Vorlage der Wert mit dem with-param-Element übergeben. Auch globale Parameter sind möglich. Ihre Initialisierung erfolgt allerdings prozessorabhängig, beispielsweise bei Kommandozeilenaufruf mittels Wertübergabe an den Parameternamen. Eine Kombination von Vorlagenaufrufen mit Parametern kann dazu benutzt werden Probleme zu lösen, die eigentlich die Verwendung einer Schleife erfordern würden. Da diese in XSLT nicht existieren, sind zur Lösung derartiger Aufgabenstellungen rekursive Techniken einzusetzen. Beispiel 3.4.5:
Ein klassisches Beispiel für Rekursion ist die Berechnung der Fakultät. Um diese mit XSLT zu berechnen, wurde in der hier verwendeten Vorlage der Wert der zugrundeliegenden Berechnung direkt in dem Stylesheet angegeben. Das Ergebnis der Vorlage ist somit unabhängig von dem XML-Dokument, auf das diese angewendet wird. In der Vorlage für die Wurzel wird ein ergebnis-Element erzeugt, das zum Inhalt den Wert der fakultaet-Vorlage mit Startparameter a=5 besitzt. Die aufgerufene Vorlage testet, ob der übergebene Parameter größer Null ist. Wenn dieses der Fall ist, so wird die gleiche Vorlage nochmals mit dem um eins reduzierten Parameterwert aufgerufen. Das zurückgelieferte Ergebnis, mit dem Parameterwert multipliziert, liefert dann das Ergebnis. Als Abbruchbedingung für die Rekursion wird 1 zurückgeliefert, wenn der Parameter kleiner oder gleich eins ist.
<xsl:template match="/">
  <xsl:element name="ergebnis">
    <xsl:call-template name="fakultaet">
      <xsl:with-param name="a" select="'5'"/>
    </xsl:call-template>
  </xsl:element>
</xsl:template>

<xsl:template name="fakultaet">
  <xsl:param name="a"/>
  <xsl:if test="$a &gt; 1">
    <xsl:variable name="erg">
      <xsl:call-template name="fakultaet">
        <xsl:with-param name="a" select="$a - 1"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:value-of select="$a * $erg"/>
  </xsl:if>
  <xsl:if test="$a &lt;= 1">
    <xsl:value-of select="'1'"/>
  </xsl:if>
</xsl:template>
Durch Einsatz und Kombination dieser oben aufgeführten Möglichkeiten erreicht XSLT die Mächtigkeit viele geforderte Aufgaben zu lösen. Es sind noch einige weitere Elemente dafür von Nutzen. Ein Beispiel hierfür ist das sort-Element, mit dem sich Elemente nach bestimmten Eigenschaften innerhalb von apply-templates oder for-each-Elementen sortieren lassen. Damit wird die Reihenfolge, in der die gefundenen Knoten abgearbeitet werden, festgelegt. Zur Auswertung bestimmter Elemente, auch über verschiedene Ebenen hinweg, dient das number-Element. Mit ihm können Knoten oder auch Werte gezählt, weiter berechnet und formatiert ausgegeben werden. Eine typische Anwendung für das number-Element ist die Durchnummerierung der Knoten anhand ihrer Position im Baum. Eine andere Möglichkeit, wenn es um die Formatierung von Werten für die Ausgabe geht, liefert das decimal-format-Element. Mit diesem Element lassen sich Formatierungsregeln definieren, die an unterschiedlichen Stellen innerhalb des Stylesheets wieder aufgerufen werden können, wenn numerische Werte in den Ergebnisbaum übernommen werden müssen. Eine eindeutige Indizierung von bestimmten Elementen anhand festgelegter Eigenschaften, lässt sich mit dem key-Element erreichen. Durch diesen Index können beispielsweise Querverweise innerhalb des Baumes erzeugt werden. Auf einen derart erzeugten Schlüssel, der nur global existieren kann, kann innerhalb des gesamten Dokumentes zugegriffen und die dazugehörigen Elemente abgefragt werden. Um Struktur und Übersichtlichkeit in großen Stylesheets zu erreichen, lassen sich diese auf verschiedene kleinere Stylesheets aufteilen. Auch die Wiederverwertbarkeit wird durch diese Modularisierung gewährleistet. Es gibt zwei Möglichkeiten verschiedene XSLT's zusammenzufügen, import und include. Beide können nur als Top-Level-Element, also direkt unterhalb des stylesheet-Elementes, eingesetzt werden. Soll das import-Element benutzt werden, so muss dieses direkt an erster Position innerhalb des stylesheet-Elementes auftreten. Mit ihm lassen sich andere Stylesheets importieren, deren Vorlagen allerdings eine niedrigere Priorität besitzen, als es standardmäßig üblich ist. Allen Vorlagen werden Prioritäten mitgegeben. Diese ergeben sich aus der Genauigkeit des XPath-Ausdruckes, mit dem sie erstellt werden. Somit wird immer die Vorlage auf einen Knoten angewendet, deren Ausdruck diesen am exaktesten getroffen hat. Um in einzelnen Fällen selber Einfluss darauf zu nehmen, lässt sich die Priorität einer Vorlage auch von außen festlegen. Importierte Vorlagen werden somit immer nur zuletzt angewendet, wenn keine mit höherer Priorität auf den Knoten passen. Das Einfügen von Stylesheets mittels include ist an jeder beliebigen Stelle unterhalb des stylesheet-Elementes möglich. Alle eingefügten Vorlagen besitzen die gleiche Priorität, wie die direkt definierten Vorlagen. Besonders zur Aufteilung auf unterschiedliche Dateien bei großen Mengen an Vorlagen, wird diese Methode verwendet.
next up previous contents
Nächste Seite: 3.5 Funktionen Aufwärts: 3 XSLT Vorherige Seite: 3.3 Grundlagen   Inhalt
Tanja Schniederberend 2003-06-11