Websiteentwicklung: XSLT: Erste Schritte

Einführende Beispiele

Bearbeiten

In diesem Kapitel soll es darum gehen, kleine einführende Beispiele zu analysieren, bei dem die grundsätzliche Idee hinter XSLT deutlich wird. Konkret wird es ein Hallo, Welt!-Beispiel, welches wir in einige verschiedene Ausgabeformate transformieren.

Generell kennzeichnet Hallo, Welt!-Beispiele, dass sie keine wirklich praktischen Nutzen haben, aber für den Einstieg immerhin zeigen, welche Strukturen eine Sprache im einfachsten Falle aufweist.

Gegeben sei als erstes Beispiel folgende XSLT-Datei, nennen wir sie 'hallowelt.xsl':

<stylesheet version='1.0' 
  xmlns='http://www.w3.org/1999/XSL/Transform'>
<output method="text"
  media-type="text/plain" />

<template match="/">

Hallo Welt!

</template>

</stylesheet>

Diese kann nun auf eine beliebige XML-Datei angewendet werden, sogar auf 'hallowelt.xsl' selbst. Das Ergebnis sieht in etwa wie folgt aus:

Hallo Welt!

Man prüft recht schnell, das Ergebnis ist unabhängig davon, welche Ausgangsdatei man verwendet, das Beispiel ist also banal, wie üblich für Hallo, Welt!-Beispiele käme man natürlich ohne das zu lernende Format schneller zum Ziel der Ausgabe.

Man lernt allerdings immerhin, das Wurzelelement eines XSLT-Dokumentes ist stylesheet. Alternativ und synonym kann man stattdessen auch transform als Wurzelelement verwenden. Beim Wurzelelement ist per Attribut version die zu verwendende Version von XSLT zu notieren, hier reicht die in vielen Programmen implementierte Version 1.0. Die Versionsangabe ist insofern interessant, als es ja mehr als eine Version von XSLT gibt, derzeit (2015) ist bereits die dritte Version im Stadium eines Arbeitsentwurfes. In einigen Feinheiten sind neuere Versionen nicht rückwärtskompatibel, weshalb aktuelle XSLT-Prozessoren genau wissen müssen, nach welcher Version sie arbeiten sollen. Ist der XSLT-Prozessor hingegen älter als die angegebene Version, kann dieser Warnungen ausgeben, dass nicht alle Merkmale der neuen Version implementiert sein mögen und Abweichungen auftreten können.

Ferner wird der Namensraum für XSLT notiert. Da hier nur Text ausgegeben wird, kann man den von XSLT als voreingestellt wählen. Oft wird man allerdings als Ergebnis HTML oder XML haben, nicht nur Text, dann ist es sinnvoller, den Namensraum des Ausgabeformates als Voreinstellung zu wählen und für XSLT ein Präfix festzulegen, überlicherweise wählt man da 'xsl'. Das Präfix wird dann allen Elementmarkierungen vorangestellt, die aus diesem Namensraum stammen.

Näheres zu Namensräumen kann auch im XML-Buch nachgelesen werden: Namensraum. Die Namensraumangaben werden dann in der Ausgabe einfach übernommen. Der XSLT-Prozessor überträgt dann einfach die benötigten Namensraumangaben in die Ausgabe.

Will man ein entsprechendes Beispiel mit XML-Ausgabe mit Elementen im Null-Namensraum haben, kann man folgende banale Stilvorlage verwenden:

<xsl:stylesheet version = '1.0' 
  xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>

<xsl:output method="xml" indent="yes" 
  media-type="application/xml"/>

<xsl:template match="/">
<halloWelt xml:lang="de">
  Hallo Welt!
</halloWelt>
</xsl:template>

</xsl:stylesheet>

Die Ausgabe sieht dann wie folgt aus:

<?xml version="1.0"?>
<halloWelt xml:lang="de">
  Hallo Welt!
</halloWelt>

Ohne das Präfix würde eine Fehlermeldung ausgegeben werden, weil das Element halloWelt nicht zum Namenraum von XSL gehört. Hilfsweise kann man noch einen eigenen Namensraum für die Ausgabe erfinden und dafür ein Präfix festlegen, das Ergebnis ist allerdings in der Regel nicht das, was man haben will. Also die Stilvorlage:

<stylesheet version = '1.0' 
  xmlns='http://www.w3.org/1999/XSL/Transform' 
  xmlns:x="HalloWelt">

<output method="xml" indent="yes"/>

<template match="/">
<x:halloWelt xml:lang="de">
  Hallo Welt!
</x:halloWelt>
</template>

</stylesheet>

Ausgabe:

<?xml version="1.0"?>
<x:halloWelt xmlns:x="HalloWelt" xml:lang="de">
  Hallo Welt!
</x:halloWelt>

Deswegen ist es ratsam, die XSLT-Elemente mit dem Präfix zu versehen. Da zudem einige (ältere) Programmen Mängel hinsichtlich der Auflösung von Präfixen haben könnten, ist es auch sinnvoll, für XSLT nur das Präfix 'xsl' zu verwenden.

Ansonsten ahnt man schon anhand der Namensgebung und der Unterschiede bei den einzelnen Beispielen, dass das XSLT-Element output festlegt, was wie ausgegeben wird, am Eingangsbeispiel also Text, bei den andere XML. output ist optional, wenn verwendet, dann aber immer als direktes Kindelement des Wurzelelementes.

Die Methode steht im Attribut method. Wird dies nicht angegeben, wird der Wert 'xml' angenommen. XML kennt Namensräume, deshalb muß man diese dann angemessen berücksichtigen. Neben diesem und dem eingangs verwendeten 'text' gibt es auch noch den Wert 'html' speziell für HTML, welches ja kein XML-Format ist. Für XHTML wird man also 'xml' verwenden, nicht 'html'. Die Variante 'html' berücksichtigt dann die speziellen Syntaxregeln für HTML, insbesondere für inhaltsleere Elemente, aber auch die Möglichkeit, bei Element- und Attributnamen bei jedem Buchstaben beliebig zwischen Groß- und Kleinschreibung wechseln zu können, nicht alle Attributwerte in Anführungszeichen setzen zu müssen etc. Gemeinhin wird HTML aufgrund dieser Komplexität der Syntaxregeln als Markierungssuppe bezeichnet, ist also recht fehleranfällig und natürlich dann auch im Allgemeinen nicht mehr als Quelldokument für XSLT geeignet, von daher also in mehrfacher Hinsicht eher zu vermeiden. Hinsichtlich XSLT ist ferner zu beachten, dass HTML immerhin ähnliche Notationen wie XML verwendet, aber keine Namensräume kennt. Das hat zur Konsequenz, dass die Elemente von HTML im Null-Namensraum sind, man die XSLT-Namensräume also immer mit eigenem Präfix notiert, die HTML-Elemente ohne.

Mit dem Attribut indent kann man festlegen, ob verschachtelte Elemente in der Ausgabe hübsch eingerückt werden sollen, was die Lesbarkeit des Quelltextes des Ausgabedokumentes verbessert, was aber keinen Einfluß auf die Bedeutung der Ausgabe hat.

Das zweite immer verwendete XSLT-Element ist template. Dieses ist ebenfalls immer direktes Kindelement des Wurzelelementes, kann allerdings bei Bedarf öfter als einmal notiert werden. Darin als Inhalt notiert ist eine Stilvorlage, also eine Anweisung, was getan werden soll, um eine Ausgabe zu produzieren. Nun ist natürlich noch anzugeben, worauf im Quelldokument die Stilvorlage überhaupt wirken soll. Dazu gibt es das Attribut match. Der Wert ist eine Pfadangabe gemäß dem Format XPath. In diesem Falle verweist der Schrägstrich einfach auf den Wurzelknoten des Quelldokumentes, diesen muß es in jedem XML-Dokument geben, weswegen es bei diesen einfachen Beispielen auch egal ist, auf welche Datei man die Transformation anwendet.

Um jetzt noch zu sehen, wie man eine XML-Ausgabe mit definiertem Namensraum erzeugt, noch ein weiteres banales Beispiel, diesmal mit SVG als Ausgabeformat:

<xsl:stylesheet version = '1.0' 
  xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
  xmlns="http://www.w3.org/2000/svg">

<xsl:output method="xml" indent="yes"
  media-type="image/svg+xml"/>

<xsl:template match="/">
<svg xml:lang="de" version="1.1" viewBox="-100 -70 200 100">
  <title>Hallo Welt!</title>
  <text text-anchor="middle" 
        font-size="20" 
        font-family="sans-serif">Grüß dich!</text>
</svg>
</xsl:template>

</xsl:stylesheet>

Ausgabe:

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="de" 
  version="1.1" viewBox="-100 -70 200 100">
  <title>Hallo Welt!</title>
  <text text-anchor="middle" 
        font-size="20" 
        font-family="sans-serif">Grüß dich!</text>
</svg>

Wie man sieht, überträgt der Prozessor den Namensraum automatisch und korrekt in das Wurzelelement des Ausgabedokumentes. Vorsichtshalber ist zudem bei output noch mit dem Attribut media-type der Medientyp für SVG angegeben, was hilfreich sein kann, je nachdem was weiter mit der Ausgabe passiert, etwa wenn sie direkt dargestellt werden soll, kann es hilfreich für das Darstellungsprogramm sein, direkt angegeben zu bekommen, was für ein Format da produziert wurde. Ansonsten stellt sich das erst anhand der Namensraumangabe im ausgegebenen Dokument heraus, die dann ohnehin verbindlich ist.

Nun braucht man die Ausgabe nicht einmal direkt in dem Format zu notieren, die im Ausgabeformat steht, man kann auch weitgehend nur XSLT-Elemente verwenden, um in der Vorlage anzugeben, was ausgegeben werden soll:

<xsl:stylesheet version = '1.0' 
  xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
  xmlns="http://www.w3.org/2000/svg">

<xsl:output method="xml" indent="yes"
  media-type="image/svg+xml"/>

<xsl:template match="/">
 <xsl:element name="svg">
  <xsl:attribute name="version">1.1</xsl:attribute>
  <xsl:attribute name="xml:lang">de</xsl:attribute>
  <xsl:attribute name="viewBox">-100 -70 200 100</xsl:attribute>
  <xsl:element name="title">Hallo Welt!</xsl:element>
  <xsl:element name="text">
    <xsl:attribute name="text-anchor">middle</xsl:attribute>
    <xsl:attribute name="font-size">20</xsl:attribute>
    <xsl:attribute name="font-family">sans-serif</xsl:attribute>
    <xsl:text>Grüß dich!</xsl:text>
  </xsl:element>
 </xsl:element>
</xsl:template>
</xsl:stylesheet>

Die Ausgabe ist die gleiche wie zuvor. Offenbar hat XSLT also spezielle Elemente, um Elemente, Attribute und auch einfach Text zu erzeugen. Das kann hilfreich sein, zumal man Namen und Werte auch aus Informationen erzeugen kann, die in irgendeiner Weise im Quelldokument stehen oder die man anderweitig mit XSLT geeignet erzeugt, wofür es dann weitere spezielle XSLT-Elemente gibt.

Analog kann man statt SVG natürlich auch XHTML ausgeben:

<xsl:stylesheet version = '1.0' 
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
     xmlns="http://www.w3.org/1999/xhtml">

<xsl:output method="xml" indent="yes"
  media-type="application/xhtml+xml" />

<xsl:template match="/">
<xsl:element name="html">
  <xsl:attribute name="version">XHTML+RDFa 1.1</xsl:attribute>
  <xsl:attribute name="xml:lang">de</xsl:attribute>

  <xsl:element name="head">
    <xsl:element name="title">Hallo Welt!</xsl:element>
  </xsl:element>
  <xsl:element name="body">
    <xsl:element name="h1">Grüß dich!</xsl:element>
  </xsl:element>

</xsl:element>
</xsl:template>

</xsl:stylesheet>

Ausgabe:

 
<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml" 
  version="XHTML+RDFa 1.1" xml:lang="de">
  <head>
    <title>Hallo Welt!</title>
  </head>
  <body>
    <h1>Grüß dich!</h1>
  </body>
</html>

Oder eben auch als alternative Schreibweise:

<xsl:stylesheet version = '1.0' 
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
     xmlns="http://www.w3.org/1999/xhtml">

<xsl:output method="xml" indent="yes"
  media-type="application/xhtml+xml" />

<xsl:template match="/">
<html xml:lang="de" version="XHTML+RDFa 1.1">
  <head>
    <title>Hallo Welt!</title>
  </head>
  <body>
    <h1>Grüß dich!</h1>
  </body>
</html>
</xsl:template>
</xsl:stylesheet>

Ebenfalls möglich ist es, den Namensraum für die Ausgabe direkt in der Vorlage als voreingestellt festzulegen, weil dieser auch dort innerhalb des XSLT-Dokumentes gleichwertig festgelegt ist, dann aber natürlich nur für das Element, worin der Namensraum festgelegt ist und dessen Nachfahren, eben gemäß der allgemein festgelegten Regeln für Namensraumangaben:

<xsl:stylesheet version = '1.0' 
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>

<xsl:output method="xml" indent="yes"
  media-type="application/xhtml+xml" />

<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml" 
  xml:lang="de" version="XHTML+RDFa 1.1">
  <head>
    <title>Hallo Welt!</title>
  </head>
  <body>
    <h1>Hallo Welt!</h1>
  </body>
</html>
</xsl:template>
</xsl:stylesheet>

Folglich darf die Namensraumangabe auch bei irgendeinem Vorfahren erfolgen, etwa so:

<xsl:stylesheet version = '1.0' 
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>

<xsl:output method="xml" indent="yes"
  media-type="application/xhtml+xml" />

<xsl:template match="/" xmlns="http://www.w3.org/1999/xhtml">
<html xml:lang="de" version="XHTML+RDFa 1.1">
  <head>
    <title>Hallo Welt!</title>
  </head>
  <body>
    <h1>Hallo Welt!</h1>
  </body>
</html>
</xsl:template>
</xsl:stylesheet>

Nun wurde hier als Ausgabe XHTML+RDFa 1.1 gewählt, wo man keine Dokumenttypdeklaration braucht. Bei anderen Versionen und auch bei HTML4 sieht das anders aus, daher auch dazu noch ein banales Beispiel:

<xsl:stylesheet version = '1.0' 
  xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>

<xsl:output method="html" indent="yes" 
  doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
  doctype-system="http://www.w3.org/TR/html4/loose.dtd"
  media-type="text/html"
  encoding="ISO-8859-1"/>

<xsl:template match="/">
<html lang="de">
  <head>
    <title>Hallo Welt!</title>
  </head>
  <body>
    <h1>Hallo Welt!</h1>
  </body>
</html>
</xsl:template>
</xsl:stylesheet>

Die Angaben zur Dokumenttypdeklaration werden also einfach in output mit den Attributen doctype-public und doctype-system notiert.

Mit dem Attribut encoding wird hier zudem die gewünschte Kodierung für das Ausgabedokument notiert. Interessant ist, dass es keine direkte Angabe für das Quelldokument gibt. Sofern man dies dem XSLT-Prozessor nicht als Parameter übergibt oder übergeben kann, wird die Kodierung des Quelldokumentes folglich andweitig festgelegt. Sofern keine Instanz mit höherer Priorität darüber Auskunft erteilt, gilt die Angabe in der XML-Deklaration, beziehungsweise, sofern diese auch nicht vorhanden ist, wird für XML 'UTF-8' impliziert. Entsprechendes gilt dann für die Ausgabe, sofern man das Attribut nicht angibt oder es eine Instanz mit höherer Priorität gibt, wenn die Ausgabe interpretiert wird.

Ausgabe:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="de">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Hallo Welt!</title>
</head>
<body><h1>Hallo Welt!</h1></body>
</html>

Die Angabe zur Kodierung hat der XSLT-Prozessor hier also einschließlich der Angabe zum Medientyp selbständig als Element meta in das HTML-Dokument eingefügt. Das passiert bei XML-Dokumenten als Ausgabe im Allgemeinen natürlich nicht, schon weil ein XSLT-Prozessor das Ausgabeformat nicht notwendig selbst verstehen können muß, kann also solch ein Information auch nicht notwendig im Dokument selbst unterbringen, wohl aber unter Umständen als Meta-Information an ein anderes Programm weitergeben.

Weitere einfache Beispiele unter Berücksichtigung einer Ausgangsdatei

Bearbeiten

Nun soll in der Regel auch Information berücksichtigt werden, die in der Ausgangsdatei steht. Damit ist man dann schon näher an einer Anwendung für XSLT, Gleichwohl gilt es die Tradition von 'Hallo-Welt!'-Beispielen zu wahren, weshalb die Ausgangsdatei erst einmal minimalistisch gestaltet ist, also ein recht einfaches XML-Dokument ist, dessen Elemente im Null-Namensraum stehen, ohne Namensraumangabe hat der Inhalt also keine definierte semantische Bedeutung, auch wenn man diese recht einfach anhand der Elementnamen implizieren kann.

Ausgangsdatei

Bearbeiten

Die folgende XML-Datei enthält alles, was wir für unser erstes Beispiel brauchen. Eine kleine Programmdefinition, die ohne Formatierungshinweise auskommt. Ebenfalls benötigen wir keine DTD.

 <?xml version="1.0"?>
 <programm name="MeinErstesProgramm">
   <schreib>Hallo, Welt!</schreib>
 </programm>

Transformation nach Pascal

Bearbeiten

Eine einfache Stilvorlage, welche obige XML-Datei so bearbeitet, dass daraus ein richtiges Pascal-Programm wird, sieht zum Beispiel wie folgt aus:

 <xsl:stylesheet 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
   version="1.0">
   <xsl:output method="text" encoding="ISO-8859-1"/>
   <xsl:strip-space elements="*"/>
 
   <xsl:template match="/programm">
   program <xsl:value-of select="@name"/>;
   begin
   <xsl:apply-templates/>
   end.
   </xsl:template>
 
   <xsl:template match="schreib">
     WriteLn ('<xsl:value-of select="."/>');
   </xsl:template>
 </xsl:stylesheet>

Um Inhalte aus der Ausgangsdatei in der Vorlage zu berücksichtigen, braucht es spezielle XSLT-Elemente, um diese zu referenzieren oder besser zu extrahieren. Das bereits diskutierte match von template wählt zunächst einmal ein spezielles Element aus der Ausgangsdatei aus. Die erste Vorlage wählt das Wurzelelement aus, dies geschieht mit dem Wert '/programm' und entspricht den Pfadangaben von XPath, '/' ist wie bereits diskutiert der Wurzelknoten. In XML-Dokumenten kann es nur ein Wurzelelement geben, bei unserem Beispiel ist das programm, dessen Name dann auch im Pfad hinter dem Wurzelknoten notiert wird. Beim zweiten template wird nur der Name eines Elementes als Wert notiert, damit trifft die Vorlage auf alle Elemente mit diesem Namen zu. Da unsere einfache Ausgangsdatei aber nur ein Element schreib hat, gibt es da auch keine Notwendigkeit, um genauer auszuwählen.

Als Inhalt des Elementes schreib gibt es nur Text. Nachdem das Element selbst mit der Vorlage selektiert ist, kann darauf mit dem XSLT-Element value-of zugegriffen werden. Dies Element kann als Nachfahre von template verwendet werden. Es dient dazu, Textinhalte auszugeben. Wessen Textinhalt ausgegeben wird, wird mit dem Attribut select selektiert. Als Wert wird dazu wieder ein Pfad notiert. Das Element schreib ist ja bereits per match der Vorlage als aktuell ausgewählt worden, daher bezieht sich der Wert '.' von select auf den Textinhalt von schreib.

Bei diesem Beispiel wäre auch der Textinhalt von programm der von schreib, weil letzteres Kindelement des ersteren ist, welches sonst keinen weiteren Textinhalt hat.

Ausgewählt wird bei der ersten Vorlage allerdings nicht der Textinhalt, sondern per Angabe im Wert von select der Wert des Attributes name des Elementes programm. Dazu wird der Klammeraffe vor dem Namen des gewünschten Attributes notiert, dass das Attribut zum Element programm gehört, ist ja bereits per match in der Vorlage festgelegt.

Die Ausgabe des XSLT-Prozessors ist wie folgt:

  program MeinErstesProgramm;
  begin
 
    WriteLn ('Hallo, Welt!');
 
  end.

Dieses ist bereits ein richtiges Pascal-Programm. Dieses Programm könnte nun sofort von einem Compiler übersetzt werden um anschließend ausgeführt zu werden.

Da Pascal natürlich viel mehr Funktionen und Strukturen aufweist, wird die allgemeine Stilvorlage für eine Transformation eines Quelldokumentes nach Pascal natürlich deutlich umfangreicher sein.

Transformation nach C

Bearbeiten

Das Gleiche ist analog auch für andere Programmiersprachen durchführbar, hier versuchen wir uns einmal an C:

 <xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  version="1.0">
   <xsl:output method="text" encoding="ISO-8859-1"/>
   <xsl:strip-space elements="*"/>
 
   <xsl:template match="/programm">
   /* Programmname: <xsl:value-of select="@name"/> */
   #include &lt;stdio.h&gt;
   int main (void)
   {
   <xsl:apply-templates/>
     return 0;
   }
   </xsl:template>
 
   <xsl:template match="schreib">
     printf ("%s\n", "<xsl:value-of select="."/>");
   </xsl:template>
 
 </xsl:stylesheet>

Das Beispiel sieht dem obigen sehr ähnlich, tatsächlich sind nur die C-typischen Zeilen nicht aus obigem Beispiel übernommen. Hier ist allerdings zu beachten, dass die Zeichen '<' und '>' in XML eine besondere Bedeutung haben. Da diese Zeichen nun zufällig auch in der C-Ausgabe auftreten, aber nicht die Bedeutung von Elementmarkierungen haben, werden sie hier wie in XML allgemein notwendig maskiert.

Lassen wir obige Transformationsvorschriften auf unsere XML-Datei anwenden, so ergibt sich folgende Ausgabe:

  /* Programmname: MeinErstesProgramm */
  #include <stdio.h>
  int main (void)
  {
 
    printf ("%s\n", "Hallo, Welt!");
 
    return 0;
  }

Diese Ausgabe bedeutet wieder ein Programm, diesmal in der Programmiersprache C. Auch hier ist eine allgemeine Stilvorlage natürlich viel umfangreicher, weil auch C deutlich mehr Funktionen aufweist. Je nach Funktion und Inhalt kann es zudem auch notwendig sein, nicht nur die Bibliothek 'stdio.h' einzubinden, sondern auch noch diverse andere. Für die Erstellung einer allgemein brauchbaren Stilvorlage kann es also bereits eine Herausforderung sein, aufgrund des Inhaltes der Ausgangsdatei nur genau die benötigten Bibliotheken zur Einbindung anzugeben.

Transformation nach HTML

Bearbeiten

Während obige Ausgaben nur allgemeinen Text produzieren, kann man für das Format HTML auch eine spezielle Ausgabe bekommen, was die Arbeit etwas erleichtert.

 <xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  version="1.0">
  <xsl:output method="html" 
    encoding="ISO-8859-1" 
    doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
    doctype-system="http://www.w3.org/TR/html4/loose.dtd" />
  <xsl:strip-space elements="*"/>
 
  <xsl:template match="/programm">
   <html><head><title><xsl:value-of select="@name"/></title></head>
   <body>
   <xsl:apply-templates/>
   </body>
   </html>
  </xsl:template>
  <xsl:template match="schreib">
   <p><xsl:value-of select="."/></p>
  </xsl:template>
 </xsl:stylesheet>

Die Ausgabe nach der Transformation ist wie folgt:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>MeinErstesProgramm</title>
</head>
<body><p>Hallo, Welt!</p></body>
</html>

Nun gibt es inzwischen auch 'HTML5', welches keine DTD hat, aber eine leere Dokumenttypdeklaration haben kann, das erfordert dann weitere Tricks im XSLT-Dokument (gemeint ist hier die HTMl-Markierungssuppenvariante von 'HTML5', nicht die XML-Variante, die keine besonderen Tricks und keine leere Dokumenttypdeklaration benötigt, nur die XML-Ausgabe):

<xsl:stylesheet version = '1.0' 
  xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>

<xsl:output method="html" indent="yes"
  encoding="ISO-8859-1"/>

<xsl:template match="/">
<xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html&gt;
</xsl:text>

<html lang="de">
  <head>
    <title>Hallo Welt!</title>
  </head>
  <body>
    <h1>Hallo Welt!</h1>
  </body>
</html>
</xsl:template>
</xsl:stylesheet>

Ähnliche Konstruktionen können auch notwendig sein, wenn man eine Deklaration nur mit dem internen Teil der Dokumenttypdefinition in der Ausgabe benötigt.

Damit haben wir schone eine Menge geschafft. Wie zu sehen ist, kann eine einfache XML-Datei mit Hilfe von XSLT in ein beliebiges Ausgabeformat transformiert werden. Es ist eine der Stärken von XML, über eine eigene Transformationssprache zu verfügen.

Nähere Betrachtung der Stilvorlagen

Bearbeiten

Das Element strip-space dient dazu festzulegen, bei welchen Elementen aus Sicht von HTML und XML überschüssige Leerzeichen im Quelldokument entsorgt werden sollen:

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

Die Elemente, für die das gültig ist, können als mit Leerzeichen separierte Liste als Attributwert von elements angegeben werden. Ein Stern bedeutet alle. Die hierzu umgekehrte Anweisung lautet

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

Ohne eine Angabe stehen alle Elemente des Quelldokumentes in der Liste von preserve-space. Dies kann dann durch ein folgendes strip-space für eine Auswahl wieder geändert werden, entsprecht daraufhin wieder eine Änderung mit preserve-space.

Das Element template repräsentiert wie bereits erwähnt eine einzelne Vorlage:

 <xsl:template match="PFAD">
 ...
 </xsl:template>

Der Pfad 'PFAD' ist ein XPath. So meint der Wert '/programm' bei match das ein Wurzelelement programm im Quelldokument. '/' steht allgemein für das Quelldokument als Wurzel.

Wird '/programm' als Wert von match notiert und es ist kein solches Wurzelelement vorhanden, so wird die Regel nicht angewendet. Wird 'schreib' als Wert von match notiert, so findet die Regel Anwendung auf jedes Element schreib im Quelldokument. Egal, wo es steht.

Im obigen Beispiel liefern offenbar '/programm' und 'programm' das gleiche Ergebnis, was hier aber nur daran liegt, dass es keine weiteren Elemente programm innerhalb des Wurzelelementes programm gibt.

Man kann bei Bedarf auch einzeln notieren:

  <xsl:template match="/">
 ...
 </xsl:template>

 <xsl:template match="programm">
 ...
 </xsl:template>

 <xsl:template match="schreib">
 ...
 </xsl:template>

Das Element schreib könnten wir in unserem speziellen Beispiel auch mit folgendem Ausdruck ansprechen:

 <xsl:template match="/programm/schreib">
 ...
 </xsl:template>

Notiert man nun etwas im Element template, so wird dies in das Ausgabedokument übertragen:

 <xsl:template match="PFAD">
   Text
 </xsl:template>

Dieser Text wird so wie er da steht übernommen.

Daneben können in template auch einige andere Elemente von XSLT notiert werden, diese bewirken dann spezielle Aktionen, die auszuführen sind.

Zum Beispiel könnte man folgendes notieren:

 <xsl:apply-templates/>

Dies bedeutet: Verfolge alle enthaltenen Knoten und wende die gegebenenfalls vorhandene weitere Vorlagen bei den Knoten an. Bei unserer kleinen XML-Datei bedeutet das: 'Kümmere dich um den Knoten schreib.

Der Textinhalt des Elementes schreib kann wie folgt ausgegeben werden:

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

In unserem Fall also 'Hallo, Welt!'. Um die Attribute eines Knotens auszugeben, wird für select ein anderer Attributwert notiert:

<xsl:value-of select="@name"/>

Der Klammeraffe bedeutet die Referenzierung eines Attributes, hier mit dem Namen 'name', welches wiederum zum selektierten Element passen muß. Zum Element programm gehört ein solches Attribut name, hat man also passend selektiert, wird der Attributwert ausgeben.

Verarbeitung datenbasierter Eingaben

Bearbeiten

Um auch ein Beispiel für eher Datenbank-ähnliche Ausgangsdokumente zu haben, dient für die nun folgenden Beispiele diese Adressdatei als Grundlage:

<?xml version="1.0"?>
<adressdatei>
  <adresse>
    <name>Hans Müller</name>
    <strasse>Hansastraße 5</strasse>
    <stadt>44555 Musterstadt</stadt>
  </adresse>
  <adresse>
    <name>Peter Meier</name>
    <strasse>Testallee 23</strasse>
    <stadt>12345 Musterheim</stadt>
  </adresse>
  <adresse>
    <name>Markus Schmidt</name>
    <strasse>Am Mustergäßchen 42</strasse>
    <stadt>00700 Geheimstadt</stadt>
  </adresse>
</adressdatei>

Adressetiketten

Bearbeiten

Die folgende Transformation dient dazu, Adressetiketten auszugeben, die einzelnen Adressen mit einer Nummer zu versehen und einen Statusbericht über die Summe aller Adressen und behandelten Adressdateien zu generieren.

<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  version="1.0">
<xsl:output method="text" encoding="ISO-8859-1"/>

  <xsl:template match="/adressdatei">
    Anzahl Adressdateien: <xsl:value-of select="count(/adressdatei)"/> Stück
    Anzahl Adressen: <xsl:value-of select="count(/adressdatei/adresse)"/> Stück
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="adresse">
    <xsl:number/>
    <xsl:value-of select="."/>
  </xsl:template>

</xsl:stylesheet>

Die Ausgabe des XSLT-Prozessors ist wie folgt:


    Anzahl Adressdateien: 1 Stück
    Anzahl Adressen: 3 Stück

  1
    Hans Müller
    Hansastraße 5
    44555 Musterstadt

  2
    Peter Meier
    Testallee 23
    12345 Musterheim

  3
    Markus Schmidt
    Am Mustergäßchen 42
    00700 Geheimstadt


Mit dem XSLT-Element value-of samt Attribut select="count(/adressdatei/adresse)"/" bestimmen wir die Anzahl der Adressen. Die Funktion 'count()' zählt die Anzahl der ihr übergebenen Knoten. Das XSLT-Element number gibt hier die Nummer des aktuellen Elementes adresse aus, kann aber, wie wir später sehen werden, noch viel mehr.

Rechnung

Bearbeiten

Eine Rechnungsabteilung würde sich wenig für die konkreten Adressen interessieren, sondern mehr dafür, wieviel Briefe mit aufgeklebten Adressetiketten denn gekostet haben. Solche Rechnungsfälle lassen sich wie folgt abdecken:

<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  version="1.0">
<xsl:output method="text" encoding="ISO-8859-1"/>
  <xsl:template match="/adressdatei">
    Anzahl Adressen: <xsl:value-of select="count(/adressdatei/adresse)"/> Stück
    Kosten:          <xsl:value-of select="count(/adressdatei/adresse) * 0.56"/> Euro
  </xsl:template>
</xsl:stylesheet>

Die Ausgabe der Transformation:


   Anzahl Adressen: 3 Stück
   Kosten:          1.68 Euro

Per XSLT-Element value-of mit dem Atribut select mit dem Wert "count(/adressdatei/adresse) * 0.56" lässt sich offensichtlich auch rechnen. XSLT beeinhaltet allerdings nur die Grundrechenarten, weniger einfache Rechenanwendungen können also aufwendiger oder auch undurchführbar sein.

Zusammenfassung

Bearbeiten

Mit XSLT kann man XML-Dokumente in andere Formate umwandeln, wobei Textersetzungen durchgeführt werden können und Angaben über die Art und Position von Knoten gemacht werden kann. Einfache Rechnungen können problemlos durchgeführt werden. Mit XSLT lässt sich ein leistungsstarker Mechanismus aufbauen, die Daten von der eigentlichen Interpretation und Gestaltung zu trennen. Treten bei der Ausgangsdatei oder auch bei der Ausgabe Namensräume auf, so sind diese in der Stilvorlage zu berücksichtigen.

Die folgenden Kapitel bieten ihnen einen tieferen Einblick in die Details dieses mächtigen Werkzeuges XSLT.