Stil-Leben
Fast zwei Jahre, nachdem das W3C die Syntax von XML festgeschrieben hat, sieht es aus, als stünden Teile der Formatierung vor dem Abschluss. Bei XSLT und XPath handelt es sich um die Entwürfe für die Dokumententransformation von einer in die andere Struktur.
- Henning Behme
Was DSSSL für SGML ist, soll die Extensible Stylesheet Language (XSL) für XML werden: die Transformations- und Formatierungssprache. Deren erste Bestandteile, die XSL Transformations und XPath, stehen derzeit beim World Wide Web Consortium (W3C) kurz vor der Verabschiedung; die sogenannte Proposed Recommendations (PR) sollte bereits am 27. September vorliegen. Erst seit dem 8. Oktober (nach Redaktionsschluss) sind sie unter den folgenden Adressen zu finden: http://www.w3.org/TR/xslt beziehungsweise http://www.w3.org/TR/xpath. Mit ihrer Hilfe lassen sich Dokumente einer XML-Struktur in die einer anderen wandeln - oder in HTML.
XSL(T) hat sich seit den ersten Entwürfen verändert und in seiner wahrscheinlich endgültigen Form nicht mehr viel mit der gemein, die der erste iX-Artikel (siehe [1]) zu diesem Thema behandelte. Der ‘heutige’ bietet nur einen groben Überblick. Angesichts des Umfangs kann er keine Einführung oder gar umfassende Darstellung sein. Wie man praktisch mit den Transformationen umgeht, muss einem anderen Artikel vorbehalten bleiben.
Online-Quellen
- XSL - Entwurf für das Formatieren
- XSLT - Proposed Recommendation für die XSL-Transformationen
- XPath - Proposed Recommendation für die expression language
- XPointer - Entwurf für XML-Links (Referenzieren von DOkumentteilen etc.)
- Namespaces - Recommendation
Bei Erscheinen dieses Heftes wird es mindestens ein Tool geben, das die PR umsetzt: XT von James Clark. Es war gleichzeitig mit der Veröffentlichung der Spezifikation auf deren Stand. Kein Wunder, Clark ist ihr Herausgeber.
Seit dem 21. April 1999 ist die Formatierungssprache XSL in mehrere Bereiche aufgeteilt. Die eigentliche Formatierung - Seitenlayout, Fonts, Farben et cetera - bleibt XSL vorbehalten, aber die Transformationen sind in XSLT und XPath ausgegliedert. Letztere beschreibt die Möglichkeiten, auf Teile eines XML-Dokuments zu verweisen. Sowohl XSLT als auch die sogenannten XPointer (Linking) sollen XPath verwenden.
Von Schablonen und Mustern
Bei den Transformationen, die XSLT vornimmt, handelt es sich um die Wandlung eines Dokumentenquellbaums (source tree) in einen Ergebnisbaum (result tree). Die Datei, die diese Transformationsanweisungen enthält, nennt man ein Stylesheet - a) aus historischen Gründen (auch DSSSL hieß Stylesheet-Sprache) und b) weil sie schlicht Formatierungsanweisungen für XSL generieren kann. Der Mantel eines solchen Stylesheet sieht aus wie Listing 1, wobei statt des Bezugs zum europäischen. Latin1-Zeichensatzes auch UTF-8 und UTF-16 stehen können (die letzten beiden muss jeder XSL-Prozessor unterstützen).
LISTING 1: Stylesheet-Mantel
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/XSL/Transform">
<!-- Rest des Stylesheets -->
</xsl:stylesheet>
Stylesheets sind selbst XML-Dokumente. Sie enthalten daher an ihrem Anfang eine Processing Instruction, die die XML-Version und, hier, den Zeichensatz definiert. Außerdem legt das Wurzelelement xsl:stylesheet, das dem Namensraum xsl angehört, fest, dass der XSL-Namensraum der von XSLT in der Version 1 ist. Innerhalb dieses Wurzelelements können eine Reihe sogenannter Top-Level-Elemente vorkommen, die der fast gleichnamige Kasten enthält.
Top-level-Elemente in XSL-Stylesheets
<xsl:import href="..."/>
<xsl:include href="..."/>
<xsl:strip-space elements="..."/>
<xsl:preserve-space elements="..."/>
<xsl:output method="..."/>
<xsl:key name="..." match="..." use="..."/>
<xsl:locale name="...">...</xsl:locale>
<xsl:attribute-set name="...">...</xsl:attribute-set>
<xsl:variable name="...">...</xsl:variable>
<xsl:param name="...">...</xsl:param>
<xsl:template match="...">...</xsl:template>
<xsl:template name="...">...</xsl:template>
Wer XML in HTML wandeln will, muss dies über das Top-Level-Element output kundtun (siehe Listing 2). Mit Hilfe der Attributzuweisung method="html" kann man dem XSLT-Prozessor mitteilen, was als Ergebnisbaum gewünscht ist.
LISTING 2: Default-Namensraum HTML
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/XSL/Transform">
<xsl:output method="html"/>
<!-- Rest des Stylesheets -->
</xsl:stylesheet>
Stylesheets sind eine Ansammlung von Regeln (template rules), die jeweils aus zwei Teilen bestehen:
- Muster (pattern),
- Schablone (template).
Der XSL-Prozessor vergleicht das Muster mit den Knoten im Quellbaum, und die Schablonen dienen der Generierung des Ergebnisbaums. Dabei berücksichtigen Prozessoren nur Elemente, für die in einer solchen Vorlage Anweisungen existieren. Eine einzelne Schablone kann bereits eine komplexe Struktur erzeugen, es können aber auch viele zur Komplexität des resultierenden Dokuments beitragen.
Handelt es sich bei den zugrunde liegenden XML-Daten um tief verzweigende/strukturierte, kann auch das Stylesheet umfangreich und komplex sein. Nicht nur deshalb sieht das W3C vor, dass Webautoren in ihren Stylesheets andere referenzieren können. Das ist auf zweierlei Weise möglich:
<xsl:import href="..."/>
<xsl:include href="..."/>
In beiden Fällen ersetzt der Stylesheet-Prozessor die Referenz durch den Inhalt der inkludierten Datei. Mit einem Unterschied. Bei Überschneidungen entscheidet bei <xsl:import href="..."/> das importierende Stylesheet, welche Regeln Priorität haben. Im Falle von <xsl:include href="..."/> gelten die Konfliktlösungsregeln, die die Spezifikation vorsieht. Konkret heißt das: Wer vom allgemeinen Fall zum besonderen vorgehen will, sollte import verwenden. Wichtig ist, dass beide nur als Top-Level-Elemente vorkommen können und import unbedingt als erstes dieser TLDs stehen muss.
Listing 3 zeigt einen Ausschnitt aus einem Stylesheet namens poem.xsl, das die Ausgabe von Gedichten beschreibt. Listing 4 bindet es ein, sieht aber vor, dass die jeweils letzte Zeile einer Strophe (<xsl:if test="position()=last()">) um 75 Pixel eingerückt wird.
LISTING 3: Zeilenausgabe
<xsl:template match="line">
<xsl:apply-templates /><br />
</xsl:template>
LISTING 4: Stylesheet einbinden
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/XSL/Transform">
<xsl:output method="html"/>
<xsl:import href="poem.xsl"/>
<xsl:template match="line">
<xsl:if test="position()=last()">
<img src="images/1pixel.gif" width="75" height="1" />
</xsl:if>
<xsl:apply-templates/><br />
</xsl:template>
</xsl:stylesheet>
XSLT ermöglicht im Prinzip beliebige Transformationen. Aus der Rechnung von Firma A kann ein Stylesheet beispielsweise eine Struktur erzeugen, auf die sich A und Firma B geeinigt haben, um solche Daten auszutauschen. Firma B wiederum muss möglicherweise das Zwischenformat erst wieder in die hauseigene Struktur wandeln - ohne dass die Integrität der Daten darunter leidet. Und: die Bedeutung der Information bleibt erhalten. Genau die geht bekanntlich verloren, wenn man HTML erzeugt.
Darreichungsform HTML
Schon angesichts der schleppenden Entwicklung der Browser, was die Darstellung von XML-Dokumenten angeht, und weil auch künftig nicht alle Viewer XML ‘nativ’ unterstützen dürften, werden diejenigen, die ihre Webseiten aus XML-Beständen servieren, den Umweg über HTML-Dateien ins WWW nehmen. Aber auch die Wahrung des Besitzstandes ist in diesem Zusammenhang ein Argument: Wer komplexe Daten sein Eigen nennt, will sie möglicherweise nur häppchenweise zur Verfügung stellen.
Erste Voraussetzung für die Generierung von HTML aus XML ist, wie erwähnt, das in Listing 2 Stehende. Es bewirkt, dass Autoren innerhalb des Stylesheet HTML-Elemente ohne Nennung des Namensraums verwenden können. Ein einfaches Beispiel zeigt Listing 5. Die Wurzel des Dokuments wird durch die Anweisungen ersetzt, die die Schablone mit dem Muster match="/" enthält, in diesem Fall die schon erwähnte Formatierung eines Gedichts. Aus den einer DTD von David Megginson entnommenen Elementen stanza (Strophe) und line (Zeile) erzeugt das Stylesheet Absätze (p) beziehungsweise Inline-Sequenzen, die ein Return (<br>) abschließt. Da <br> ein leeres Element ist, muss es innerhalb von XSLT als solches ausgewiesen sein: durch den Schrägstrich vor dem schließenden Größer-als-Zeichen (<br/>).
LISTING 5: Gedicht nach HTML transformieren
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<head>
<title><xsl:apply-templates select="poem/title" mode="head"/></title>
</head>
<body>
<xsl:apply-templates select="poem"/>
</body>
</html>
</xsl:template>
<xsl:template match="poem">
<xsl:apply-templates select="stanza"/>
</xsl:template>
<xsl:template match="stanza">
<p><xsl:apply-templates select="line"/></p>
</xsl:template>
<xsl:template match="line">
<xsl:apply-templates /><br />
</xsl:template>
<xsl:template match="title">
<h3><xsl:value-of select="."/></h3>
</xsl:template>
<xsl:template match="title" mode="head">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
Die einfache Struktur des Dokuments ist der Grund dafür, dass auch das Stylesheet keine Komplexität aufweist. Einzig die Behandlung des Titels zeigt eine der Möglichkeiten, die XSLT bietet: Modes, wie sie ähnlich von DSSSL her bekannt sind. Grund für die Existenz von zwei Schablonen ist, dass der Titel zweimal - auf unterschiedliche Weise - benötigt wird: In der Darstellung des Textes soll er als <h3>-Überschrift zu sehen sein, aber das macht im <head>-<title> keinen Sinn, weil der in der Browser-Dachleiste steht. Der Modus ‘head’ sorgt dafür, dass in dieser Leiste keine HTML-Elemente stehen.
Mit James Clarks XT lässt sich eine XML-Instanz leicht in HTML wandeln. Ein Script wie goxt (Listing 6) vorausgesetzt, reicht der Aufruf goxt quelle transformationsdatei ziel ohne die dazugehörigen Endungen.
LISTING 6: goxt
java -Dcom.jclark.xsl.sax.parser=com.jclark.xml.sax.Driver \
com.jclark.xsl.sax.Driver \
$1.xml $2.xsl $3.html
Natürlich bietet XSLT wesentlich mehr Möglichkeiten, als hier zu ahnen ist. Der Kasten ‘Musterliste’ beispielsweise enthält eine Reihe von Patterns, mit denen auf Elemente und Attribute des Quellbaums zugegriffen werden kann. Außerdem beinhaltet XSLT einige Funktionen (siehe oben position()), und das ‘X’ im Namen (Extensibility) suggeriert: es wird auch Möglichkeiten geben, eigene Funktionen zu integrieren.
Musterliste | |
Die folgenden Muster entstammen der XSLT-Spezifikation: | |
/ | Wurzelelement |
* | jedes Element |
@* | jedes Attribut |
@class | jedes Attribut class |
absatz | jedes Element absatz |
absatz|einschub | jedes Element absatz oder einschub |
liste/list-el | jedes list-el als Kind von liste |
buch//absatz | jedes Element absatz unterhalb von buch |
text() | Textelemente |
processing-instruction() | jede Verarbeitungsanweisung |
node() | jeder Knoten; keine Attribute und nicht das Wurzelement |
id("a1") | Element mit der id ‘a1’ |
absatz[1] | jedes Element absatz, das das erste Kind seines übergeordneten Elements ist |
*[position()=1 and self::absatz] | dito |
absatz[last()=1] | Element absatz, das das einzige Kindelement des übergeordneten Elements ist |
liste/list-el[position()>1] | jedes list-el-Element als Kind einer liste, das nicht deren erstes Kindelement ist |
list-el[position() mod 2 = 1] | trifft jedes ungerade Element list-el |
kapitel[@class="anhang"]//absatz | jedes Element absatz mit einem Ahnen kapitel, dessen Attributwert für class ‘anhang’ ist |
Nummerierung (<xsl:number value="position()" format="1. "/>) und bedingte Verarbeitung (xsl:if und xsl:choose) sind ebenso möglich wie Sortieren und die Übergabe von Parametern an Regeln. Mehr dazu in einem späteren Artikel.
Literatur
[1] Henning Behme; Web-Programmierung; Daten verpflichten; XSL: die Stil-Sprache für XML (hb)