Eine exemplarische Transformation mit XSLT
7.3 Eine exemplarische Transformation mit XSLT

Als Beispiel für eine Transformation mit XSLT gehen wir von folgendem XML-Dokument aus:

Beispiel 7.2 Ausgangsdokument für eine einfache XSLT-Transformation

<!DOCTYPE nitf SYSTEM 
  "http://www.nitf.org/site/nitf/documentation/nitf-3-0.dtd">

<?xml-stylesheet href="astronews_to_html.xsl" type="text/xml"?>
<nitf version="-//IPTC//DTD NITF 3.0//EN" 
      change.date="October 12, 2001" change.time="14:00">
  <head>
    <docdata>
      <doc-id id-string='2002_11_14_IT_AN_01'/>
      <date.release norm='20021114'/>
      <doc-scope scope='Sonne'/>
      <doc-scope scope='Sonnenflecken'/>
      <key-list>
        <keyword key="Adaptive Optik"/>
        <keyword key="Magnetismus"/>
      </key-list>
    </docdata>
  </head>
  <body>
    <body.head>
      <hedline>
        <hl1>Bisher detailreichste Aufnahmen der Sonnen-Oberfläche 
          veröffentlicht</hl1>
      </hedline>
    </body.head>
    <body.content>
      <p class="summary">Schwedische Forscher um <person>Dan
      Kiselman</person> haben bekanntgegeben, dass sie die bisher
      schärfsten Aufnahmen der Sonnenoberfläche machen konnten. In
      einem Artikel des Magazins Nature veröffentlichten sie Bilder,
      die mit dem schwedischen 1-m-Sonnenteleskop auf der Kanareninsel
      La Palma gemacht wurden. Das Teleskop verwendet adaptive Optik,
      um atmosphärische Störungen zu korrigieren.</p>

      <hl2>Adaptive Optik erstmals bei der Sonnenbeobachtung eingesetzt</hl2>
      
        <p>Mit dem neuen Teleskop auf La Palma, das unter der
      Schirmherrschaft der <org>Schwedischen Akademie der
      Wissenschaften</org> steht, wurde in diesem Frühjahr eines der
      leistungsstärksten erdgestützten Sonnenteleskope in Betrieb
      genommen. Seine so genannte Adaptive Optik filtert
      atmosphärische Störungen heraus und liefert Bilder von so hoher
      Auflösung, wie sie sonst nur von Teleskopen im Weltraum erreicht
      wird. Erste Ergebnisse ihrer Beobachtungen haben die
      schwedischen Sonnenforscher jetzt präsentiert.</p> 

        <hl2>Kühle Flecken auf der Sonne</hl2>

      <p>Sonnenflecken markieren kühlere Zonen auf der
      Sonnenoberfläche, sie treten vor allem in Zeiten hoher
      Sonnenaktivität auf. Die Flecken, die im Extremfall die Größe
      von Planeten erreichen, stehen in Zusammenhang mit den komplexen
      Magnetfeldern an der Sonnenoberfläche.</p>

      <p class="source"><a
      href="http://www.spacetoday.net/Summary/1303">New telescope
      provides sharpest view of Sun</a> (spacetoday.net) <a
      href="http://www.netzeitung.de/servlets/page?section=5681&amp;item=215305"
        >Sonnenhaare mit dunklem Kern</a> (Netzeitung.de)</p>

      <media media-type="image">
        
        <media-reference
            name="Foto: Royal Swedish Academy of Sciences"
            mime-type="image/jpeg"
            source="sonnenflecken.jpg"
            alternate-text="Sonnenflecken">
        </media-reference>
        <media-caption>Wie Haare umgeben die Filamente der 'Penumbra' das 
             Zentrum des Sonnenflecks.</media-caption>
      </media>
     </body.content>    
  </body>
</nitf>

Wir erhalten folgendes Ergebnis, wenn wir das Dokument mit dem unten vorgestellten Stylesheet transformieren:

Beispiel 7.3 Ergebnis der Transformation durch ein einfaches XSLT-Stylesheet

<html>
  <body>
<h3>Bisher detailreichste Aufnahmen der Sonnen-Oberfläche
veröffentlicht</h3>
<p>Schwedische Forscher um <i>Dan Kiselman</i> haben bekanntgegeben,
dass sie die bisher schärfsten Aufnahmen der Sonnenoberfläche machen
konnten. In einem Artikel des Magazins Nature veröffentlichten sie
Bilder, die mit dem schwedischen 1-m-Sonnenteleskop auf der
Kanareninsel La Palma gemacht wurden. Das Teleskop verwendet adaptive
Optik, um atmosphärische Störungen zu korrigieren.</p>
<h4>Adaptive Optik erstmals bei der Sonnenbeobachtung eingesetzt</h4>
<p>Mit dem neuen Teleskop auf La Palma, das unter der Schirmherrschaft
der <i>Schwedischen Akademie der Wissenschaften</i> steht, wurde in
diesem Frühjahr eines der leistungsstärksten erdgestützten
Sonnenteleskope in Betrieb genommen. Seine so genannte Adaptive Optik
filtert atmosphärische Störungen heraus und liefert Bilder von so
hoher Auflösung, wie sie sonst nur von Teleskopen im Weltraum erreicht
wird. Erste Ergebnisse ihrer Beobachtungen haben die schwedischen
Sonnenforscher jetzt präsentiert.</p>
<h4>Kühle Flecken auf der Sonne</h4>
<p>Sonnenflecken markieren kühlere Zonen auf der Sonnenoberfläche, sie
treten vor allem in Zeiten hoher Sonnenaktivität auf. Die Flecken, die
im Extremfall die Größe von Planeten erreichen, stehen in Zusammenhang
mit den komplexen Magnetfeldern an der Sonnenoberfläche.</p>
<p>New telescope provides sharpest view of Sun: <a
href="http://www.spacetoday.net/Summary/1303"
target="new">http://www.spacetoday.net/Summary/1303</a>
(spacetoday.net) Sonnenhaare mit dunklem Kern: <a
href="http://www.netzeitung.de/servlets/page?section=5681&amp;item=215305"
target="new"
>http://www.netzeitung.de/servlets/page?section=5681&amp;item=215305</a>
(Netzeitung.de)</p>
<img src="sonnenflecken.jpg" alt="Sonnenflecken"><p>Wie Haare umgeben
die Filamente der 'Penumbra' das Zentrum des
Sonnenflecks.</p>Stichwörter: <b>Adaptive Optik</b> <b>Magnetismus</b>
</body>
</html>

Diese Transformation wurde mit dem Stylesheet aus Beispiel 7.4 durchgeführt.

Beispiel 7.4 Ein einfaches XSLT-Stylesheet

<?xml version='1.0' encoding="iso-8859-1" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version='1.0'>							1) 

<xsl:output method="html" encoding="iso-8859-1"/>				2) 

 <xsl:template match="/">							3)            
  <html>
    <xsl:apply-templates/>
  </html>
</xsl:template>

<xsl:template match="title">
  <head>
    <title>
      <xsl:value-of select="."/>						4) 

    </title>
  </head>
</xsl:template>

<xsl:template match="body">							5)            
  <body>
    <xsl:apply-templates select="body.head/hedline/hl1"/>

    <xsl:apply-templates select="body.content/*"/>
    <xsl:call-template name="keywords"/>					6) 

  </body>
</xsl:template>

<xsl:template match="body.head/hedline/hl1"> 

  <h3>
    <xsl:value-of select="."/>
  </h3>
</xsl:template>

<xsl:template match="p">
  <p>
    <xsl:apply-templates/>
  </p>
</xsl:template>
<xsl:template match="hl2">
  <h4>
    <xsl:value-of select="."/>
  </h4>
</xsl:template>

<xsl:template match="org">
  <i>
     <xsl:value-of select="."/>
  </i>
</xsl:template>
<xsl:template match="person">
  <i>
    <xsl:value-of select="."/>
  </i>
</xsl:template>

<xsl:template match="media">							7)               

  <xsl:element name="img">
    <xsl:attribute name="src">
      <xsl:value-of select="media-reference/@source"/>
    </xsl:attribute>
    <xsl:attribute name="alt">
      <xsl:value-of select="media-reference/@alternate-text"/>
    </xsl:attribute>
  </xsl:element>
  <xsl:element name="p">
    <xsl:value-of select="media-caption"/>
  </xsl:element>
</xsl:template>
    

<xsl:template match="a">							8)        

  <xsl:value-of select="."/>
  <xsl:text>:  </xsl:text>
  <xsl:element name="a" use-attribute-sets="attribs">				9) 

    <xsl:value-of select="@href"/>
  </xsl:element>
</xsl:template>

  <xsl:attribute-set name="attribs">						10) 

    <xsl:attribute name="href">
      <xsl:value-of select="@href"/>
    </xsl:attribute>
    <xsl:attribute name="target">
        <xsl:text>new</xsl:text>
    </xsl:attribute>  
  </xsl:attribute-set>

  <xsl:template name="keywords">						11)          

    <xsl:text>Stichwörter: </xsl:text>
    <xsl:for-each select="//head/docdata/key-list/keyword">

      <b>
        <xsl:value-of select="@key"/>
      </b>
        <xsl:text>  </xsl:text>
      </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>




  1. Das Stylesheet beginnt mit der XML-Deklaration, gefolgt vom Dokumentelement, in dem auch der Namensraum für die XSLT-Elemente angegeben wird:

    <?xml version='1.0' encoding="iso-8859-1" ?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    version='1.0'>

    Das Dokumentelement eines XSLT-Stylesheets ist meist vom Typ stylesheet; als Alternative ist auch der Elementtyp transform möglich. Die Angabe einer Versionsnummer als Wert des Attributs version ist obligatorisch. Die Reihenfolge der Elemente innerhalb des Dokumentelements — sie werden auch als Top-Level-Elemente bezeichnet — hat (mit der Ausnahme von import-Anweisungen) keine Auswirkungen auf die Verarbeitung von Dokumenten.

    Die zu XSLT gehörenden Elemente sind im Beispiel durch das Namensraum-Präfix xsl gekennzeichnet. Dieses Präfix sollte zu Beginn des Stylesheets auf den Bezeichner http://www.w3.org/1999/XSL/Transform bezogen werden. (Wie bei allen Namensraum-Angaben ist es unerheblich, welches Präfix gewählt wird; es hat sich aber eingebürgert, xsl zu verwenden.) Ein XSLT-Stylesheet ist ein wohlgeformtes XML-Dokument, das Elemente aus dem XSLT-Namensraum enthält und andere Elemente enthalten kann. Der XSLT-Prozessor verwendet alle dem XSLT-Namensraum zugeordneten Elemente zur Erzeugung des Ergebnisbaums. Alle übrigen XML- oder XHTML-Elemente bzw. Textfragmente innerhalb des Stylesheets bilden mögliche Bestandteile des Ergebnisbaums.

  2. Das Element output gibt an, welche Ausgabeformat erzeugt werden soll. Außer HTML- sind auch XML- und Textausgaben möglich. Die Eigenschaften des Ausgabeformats lassen sich noch detaillierter angeben; im Beispiel wird lediglich die Zeichenkodierung angegeben, die für das Ausgabedokument verwendet werden soll:

    <xsl:output method="html" encoding="iso-8859-1"/>
                    

    Die Ausgabemethode html unterscheidet sich von der Methode xml nur in der verwendeten Syntax bei der Dokumenterzeugung. So wird für html die bekannte SGML-Syntax verwendet, d. h. beispielsweise, dass leere Elemente wie br weder ein Endtag besitzen, noch einen Schrägstrich unmittelbar vor der schließenden spitzen Klammer des Starttags. Die Korrektheit gegenüber einer HTML-DTD wird durch einen XSLT-Prozesser in der Regel nicht überprüft. So bleibt es in der Verantwortung des Autors eines XSLT-Stylesheets, die Gültigkeit der erzeugten Dokumente sicherzustellen.

  3. Ein XSLT-Prozessor beginnt eine Transformation immer mit der Vorlage, die auf den Wurzelknoten des Eingabebaums passt. Als Wert des Attributs match ist angegeben, worauf sich das Template bezieht. Bei dem Wert dieses Attributs handelt es sich um einen XPath-Ausdruck; der Wert "/" im Beispielt wählt den Wurzelknoten aus.

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

    (Verwendet man match="nitf", ergibt sich in diesem Fall dasselbe Ergebnis für den Ergebnisbaum, allerdings nicht aus demselben Grund. Der Knoten, der das Dokumentelement repräsentiert, ist nicht der Wurzelknoten des Eingabebaums, sondern einer seiner Kindknoten. Er kann Geschwisterknoten haben, die Kommentare und Processing Instructions darstellen.)

    Der Wurzelknoten bildet den Kontext, also den Bezugsrahmen für alle Ausdrücke innerhalb des Elements template.

    Der Inhalt dieser Vorlage besagt, dass ein Element vom Typ html im Ausgabebaum erzeugt wird, wenn der Wurzelknoten der aktuelle Knoten ist. Die Anweisung apply-templates erzeugt dann die Nachkommen des Elements html. Sie schreibt vor, dass auf die Kindknoten des aktuellen Knotens die Templates des Stylesheets angewendet werden sollen.

    apply-templates ist einer der am meisten benutzten Elementtypen von XSLT. Wenn ein solches Element ohne das Attribut select verwendet wird, bewirkt es, dass die Kindknoten des aktuellen Knotens verarbeitet werden. Man kann dafür sorgen, dass alle Knoten eines Eingabebaums hierarchisch nacheinander verarbeitet werden, indem von jedem Template aus mit apply-templates jeweils alle Template-Regeln des Stylesheets rekursiv (einschließlich der gerade instantiierten Regel) für die Kindknoten angewendet werden.

  4. Die Template-Regel

    <xsl:template match="title">
      <head>
        <title>
          <xsl:value-of select="."/> 
        </title>
      </head>
    </xsl:template>
    	  

    kann potentiell auf alle Elementknoten vom Typ title angewendet werden. Sie erzeugt Elementknoten des Typs head mit einem Kindknoten des Typs title im Ergebnisbaum. Die Nachkommen des Knotens title im Ergebnisbaum werden durch das Element value-of erzeugt. Der XPath-Ausdruck "." bezeichnet den aktuellen Kontextknoten (der das Element title im Eingabebaum repräsentiert), dessen Wert an der Stelle des Elements value-of im Ergebnisbaum eingefügt werden soll. Der Wert eines Elementknotens besteht in den Zeichen, die den Inhalt des Elements bilden, genauer gesagt: in den Textknoten, die Nachkommen des entsprechenden Elementknotens sind.

    Wie eine solche Vorlage funktioniert, zeigt der Vergleich mit dem "Suchen und Ersetzen" in Textverarbeitungssystemen. Die Vorlage bezieht sich bei XSLT allerdings nicht auf Text, sondern auf die Knoten des Eingabebaums. Das Attribut match des Elementtyps template funktioniert ähnlich wie das Eingabefeld für den zu ersetzenden Ausdruck. Es gibt an, auf welchen Knoten des Eingabebaums sich die Vorlage bezieht, in diesem Fall auf Elementknoten mit dem Typ title. Es ersetzt aber nicht eine Zeichenkette durch eine andere Zeichenkette, sondern instantiiert eine Vorlage. Es teilt dem Prozessor mit: "Wo immer im Quelldokument ein Knoten vorkommt, der ein Element des Typs title repräsentiert, werte diese Vorlage aus!" Die in der Vorlage enthaltene Regel entspricht der einzusetzenden Zeichenkette beim "Suchen und Ersetzen" in einem Textverarbeitungssystem. In unserem Fall generiert sie einen Teil des Ergebnisbaums, nämlich einen Teilbaum, dessen Wurzel ein Elementknoten mit dem Typ head ist. Der einzige Kindknoten von head repräsentiert ein Element title. Der Inhalt dieses Knotens wird von dem Element value-of spezifiziert. Die Wurzelknoten der Teilbäume, die mit der Auswertung des eingebetteten Elements value-of erzeugt werden, bilden Kindknoten des neuen Elementknotens vom Typ title.

  5. Folgende Vorlage dient dazu, den Rumpf des HTML-Dokuments zu erzeugen:

    <xsl:template match="body">
      <body>
        <xsl:apply-templates select="body.head/hedline/hl1"/>
        <xsl:apply-templates select="body.content/*"/>
        <xsl:call-template name="keywords"/>
      </body>
    </xsl:template>
    	    

    Zuerst wird der Knoten erzeugt, der ein Element vom Typ body repräsentiert. Um den Inhalt zu produzieren, wird zunächst wieder eine Instruktion verwendet, die mit dem Element apply-templates festgelegt wird. Anders als im ersten Template bestimmt in diesem Fall das Attribut select, worauf sich die weitere Verarbeitung beziehen soll; sein Wert ist wiederum ein XPath-Ausdruck, dessen Evaluierung die Knoten des Eingabebaums ergibt, die verarbeitet werden sollen.

    Indem man in einer Vorlage das Element apply-templates zusammen mit dem Attribut select verwendet, kann man gezielt Teile des Eingabebaums in einer gewünschten Reihenfolge auswählen und verarbeiten — ein Verfahren, das sich empfiehlt, wenn sich die Struktur des Ausgangs- und des Zieldokuments unterscheiden. Der XPath-Ausdruck body.head/hedline/hl1 wählt die Elementknoten mit dem Typ hl1 aus, die Kinder von Elementknoten mit dem Typ hedline sind, die ihrerseits Kinder von Elementknoten mit dem Typ body.head sind, die Nachkommen des aktuellen Kontextknotens sind. Die Anweisung besagt, dass auf diese Knoten die auf sie passenden Vorlagen des Stylesheets anzuwenden sind.

    Der Ausdruck body.content/* enthält das Jokerzeichen "*"; es steht für Elementknoten mit beliebigen Typen. Der XPath-Ausdruck body.content/* wählt alle Elementknoten aus, die Nachkommen von Elementknoten mit dem Typ body.content sind, die Nachkommen des aktuellen Kontextknotens sind.

  6. Die Instantiierung einer bestimmten Vorlage kann auch erzwungen werden. Dazu versieht man sie mit einem eindeutigen Bezeichner, wie folgende Deklaration verdeutlicht:

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

    In einem Template kann eine solche Vorlage mittels des Elements call-template referenziert werden. Der Bezeichner der zu instantiierenden Vorlage wird im Attribut name von call-template angegeben. Folgendes Beispiel zeigt, wie die Vorlage mit dem Bezeichner "keywords" auf diese Weise instantiiert werden kann:

      <xsl:call-template name="keywords"/>

    Die Instantiierung der Vorlage geschieht hier nicht als Folge der Auswahl von Knoten, die mit einem Muster übereinstimmen, sondern dadurch, dass eine Vorlage von einer anderen Vorlage explizit "aufgerufen" wird. XSLT gleicht in dieser Beziehung einer funktionalen Programmiersprache, d. h. die erzwungene Instantiierung einer bestimmten Vorlage kann mit einem Funktionsaufruf gleichgesetzt werden.

    Durch die Verwendung von call-template kann der Autor eines Stylesheets die Reihenfolge kontrollieren, in der ein Dokument konvertiert wird. Darüber hinaus kann man es z. B. benutzen, um mehrfach verwendete Bestandteile eines Dokuments, z. B. Kopf- und Fußteile oder Navigationsmenüs von Webseiten immer wieder zu erzeugen, indem das jeweilige Template bei Bedarf über seinen Namen referenziert wird. Im Beispiel wird eine Liste mit Schlüsselwörtern erzeugt.

    Anders als apply-tempates verändert die Auswertung von call-template den aktuellen Knoten und die aktuelle Knotenliste nicht.

  7. Im Beispiel wird die Ausgabe durch explizite Anweisungen zum Einsetzen eines Elements und seiner Attribute in das Ausgabedokument erzeugt:

    <xsl:template match="media">
      <xsl:element name="img">
        <xsl:attribute name="src">
          <xsl:value-of select="media-reference/@source"/>
        </xsl:attribute>
        <xsl:attribute name="alt">
          <xsl:value-of select="media-reference/@alternate-text"/>
        </xsl:attribute>
      </xsl:element>
      <xsl:element name="p">
        <xsl:value-of select="media-caption"/>
      </xsl:element>
    </xsl:template>

    Die Auswertung eines Elements vom Typ element erzeugt einen neuen Elementknoten, dessen Name als Wert des Attributs name angegeben wird. Innerhalb des Elements element erzeugen die Elemente des Typs attribute Attribute des generierten Elements, deren Namen wiederum als Wert des Attributs name angegeben werden. (attribute muss immer innerhalb des zu erzeugenden Elements stehen.) Der Wert des Attributs wird mit dem uns schon bekannten Element value-of innerhalb von attribute angegeben. Ein Attributknoten im Eingabebaum wird dabei durch einen XPath-Ausdruck ausgewählt, bei dem das Zeichen "@" vor dem Namen des Attributs steht.

  8. Ein Textknoten kann im Ergebnisbaum mittels eines Elements des Typs text erzeugt werden; die Zeichenkette, die den Inhalt des Elements bildet, wird dabei einschließlich der Leerräume (whitespace) in das Zieldokument übernommen. Folgende Vorlage zeigt ein Beispiel für die Verwendung von text:

    <xsl:template match="a">
      <xsl:value-of select="."/>
      <xsl:text>:  </xsl:text>
    	  ...
    </xsl:template>
    

  9. Um häufig verwendete Kombinationen von Attributen nicht bei jeder Verwendung erneut schreiben zu müssen, bietet XSLT die Möglichkeit, diese mit dem Elementtyp attribute-set zu einer benannten Attributmenge zusammenzufassen.

  10. Folgendes Dokumentfragment zeigt ein Beispiel für eine Attributmenge mit dem Bezeichner "attribs":

      <xsl:attribute-set name="attribs">
        <xsl:attribute name="href">
          <xsl:value-of select="@href"/>
        </xsl:attribute>
        <xsl:attribute name="target">
            <xsl:text>new</xsl:text>
        </xsl:attribute>  
      </xsl:attribute-set>
    

    Eine solche Attributmenge kann bei der Erzeugung eines Elementknotens referenziert werden, um entsprechende Attributknoten hinzuzufügen. Dazu verfügt der Elementtyp element über ein Attribut use-attribute-set, dessen Wert die gewünschte Attributmenge benennt. Die zuvor definierte Menge "attribs" könnte also wie folgt referenziert werden:

    <xsl:element name="a" use-attribute-sets="attribs">

    Die Verwendung von Attributmengen empfiehlt sich vor allem, wenn dieselben Attribute bei unterschiedlichen Elementen verwendet werden. Es wird vor allem für Präsentationsmarkup benutzt, das eine große Menge von Attributen verwendet.

  11. Mit for-each kann man Knoten, auf die das gleiche Muster zutrifft, hintereinander abarbeiten. In der Vorlage wird eine Liste mit Stichwörtern erzeugt:

    
    <xsl:template name="keywords">
      <xsl:text>Stichwörter: </xsl:text>
        <xsl:for-each select="//head/docdata/key-list/keyword">
          <b>
            <xsl:value-of select="@key"/>
          </b>
          <xsl:text>  </xsl:text>
        </xsl:for-each>
        <br/>
        <br/>
    </xsl:template>
    	  

    for-each erleichtert es, Listen oder Inhaltsverzeichnisse zu erstellen. Das Element muss immer innerhalb einer Vorlage verwendet werden. Seine Verwendung unterscheidet sich nur wenig von der Verwendung von apply-templates mit dem Attribut select, erleichtert aber die Kontrolle über das Ergebnis. (Eine weitere Eigenschaft von for-each ist es, den aktuellen Knoten zu verändern. Bei jedem mit for-each verarbeiteten Knoten ändert sich jeweils der aktuelle Kontext. Nach der Auswertung von for-each wird wieder der ursprüngliche Kontext verwendet.)