Samstag, 11. Februar 2012 |
| |
Die sollte jeder bekommen, auch ein XSLT. Das hatte in seiner ersten Version mit ernsthaften Akzeptanzproblemen innerhalb der XML-Gemeinde zu kämpfen und dies vor allem aus zwei Gründen: es galt vielen Entwicklern als zu langsam und es war zu beschränkt in seiner Funktionalität.
Pimp up my Stylesheet
Zumindest das mit der
Funktionalität hat sich in XSLT 2.0 geändert und zwar grundlegend. Die Fülle an
neuen Funktionen ist – auch dank XPath 2.0 – so groß,
dass es schwer fällt, ein Ende zu finden.
Den Anfang macht das obligatorische stylesheet-Element (aus der Beispieldatei XSLT2.xsl):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
>
Das stylesheet-Element ist also geblieben – wie alle anderen Elemente aus XSLT 1.0 auch. Selbst der Namensraum ist derselbe. Den Unterschied macht das version-Attribut aus: "2.0" statt "1.0" – irgendwie ist grad alles "Zwei-Punkt-Null".
Doch noch eine Abweichung vom Gewohnten zeigt sich: die Namensraumdeklaration für XML Schema und die XPath-Funktionen. Letzteres ist schnell erklärt. Die zahllosen – sie zu zählen ist tatsächlich schwer – Funktionen, die mit XPath 2.0 hinzugekommen sind, haben einen eigenen Namensraum und damit auch ein eigenes Präfix bekommen: "fn" steht für "function".
Bei vollem Bewusstsein
Doch was macht XML Schema
hier? Falsche Baustelle? Nein, keineswegs. XSLT 2.0 ist XML-Schema-aware. Und weil man komplizierte Sachverhalte immer an
einem einfachen Beispiel erklärt, hier ein einfaches Beispiel (aus der Datei XSLT2.xml):
<root >
<item>2007-05-15</item>
</root>
Es dreht sich alles offensichtlich um ein Datum. Um alle Daten vor dem 16. Mai (übrigens dem Erscheinungsdatum dieses Beitrags) zu finden, nutzt das schon bekannte Stylesheet folgenden XPath-Ausdruck:
item[. lt xs:date('2007-05-16')]
Jetzt ist klar, wofür das Präfix "xs" benötigt wird: zum Beispiel, um einen Datumswert, für den es kein Literal in XPath 2.0 gibt, aus einer Zeichenfolge zu generieren. Das Präfix ist aber auch an anderer Stelle nützlich, beispielsweise zur Typprüfung:
<xsl:if test="item instance of xs:date">
Doch zurück zum Datumsvergleich. Der schlägt fehl, wenn ein nicht-validierender Parser das zugehörige XML-Dokument einliest beziehungsweise ein validierender Parser kein passendes XML Schema zur Hand hat. Dann meint "2007-05-15" nämlich nicht "der 15. Mai 2007" sondern schlichtweg "2007-05-15". Kurzum, der Parser muss Äpfel (das Datum 17.05.2007) mit Birnen (die Zeichenfolge "2007-05-15") vergleichen und das kann nur in einer Fehlermeldung enden. Wenn aber auch der XML-Parser XML-Schema-aware ist und sich des passenden Schemas (XSLT2.xsd) bedienen kann, dann funktioniert der Datumsvergleich. Das hätte es in XSLT 1.0 respektive XPath 1.0 nicht gegeben, weil sie sich eben der Existenz eines XML Schema nicht bewusst waren.
Im Ergebnis ein Baumfragment
Apropos: waren Sie sich
jemals des Ergebnisbaumfragmentes bewusst? Nein? Vielleicht kennen Sie dieses
Konstrukt auch unter anderem Namen: Result Tree Fragment, oder für Eingeweihte: RTF. Das ist nun
wirklich ein komplizierter Name. Doch wie so oft, verbirgt sich hinter einem
komplizierten Namen eine einfache Sache. Ein Beispiel in XSLT 1.0 (demnach in
der Datei XSLT1.xsl):
<xsl:variable name="temp">
<dates>
<xsl:apply-templates select="item" />
</dates>
</xsl:variable>
Es nutzt die Möglichkeiten von XSLT, Teilergebnisse in einer Variablen abzulegen, um beispielsweise so die Performance zu verbessern. Des Weiteren strukturiert es die Ergebnisse, natürlich mit Hilfe von XML-Elementen.
Dumm ist nur, dass sich die Ergebnisse nicht mehr so ohne Weiteres auslesen lassen, denn die Variable temp beherbergt eben diesen gefährlichen RTF und der macht ein Auslesen der XML-Daten aus der Variablen ohne Hilfsmittel unmöglich. Was einst als Vereinfachung für die Hersteller von XSLT-Prozessoren gedacht war, erwies sich als Schnapsidee. Weil jeder vernünftige Entwickler auf die Performance achtet, wollte auch jeder diese Möglichkeit nutzen und so spendierten fast alle Hersteller ihrem Prozessor letztendlich doch eine Erweiterungsfunktion, meist node-setgenannt. Die machte aus dem absonderlichen Result Tree Fragment ein ordentliches Node Set:
<xsl:for-each select="ms:node-set(temp)/dates/item">
In XSLT 2.0 hat sich das Thema erledigt. Es gibt keine RTFs mehr. Es gibt nur noch Node Sets. Welch eine Erleichterung!
Fazit
Umsteigen lohnt sich also! Die Vorteile – schnellere Entwicklungszeiten dank höherer Funktionalität – wiegen die Nachteile – Einarbeitungszeit in die neuen Funktionen – mehr als auf. Wer jetzt ja zu XSLT 2.0 sagt, frägt zwangsläufig: „Und was ist mit meinen bestehenden aufwendig implementierten, langjährig gereiften und überaus wichtigen XSLT-1.0-Stylesheets?“ Die gute Nachricht: es gibt Wege, ihre existierende XSLT-Bibliothek in die schöne neue Zwei-Punkt-Null-Welt zu integrieren. Doch davon und den vielen anderen neuen Funktionen (Multiple Ausgabedokumente, Grouping-Funktion, uvm.) sei hier ein andermal berichtet. In diesem Sinne, bis in vierzehn Tagen,
Ihr Martin Szugat
Martin Szugat ist früh auf XSLT 2.0 umgestiegen und hat die Kinderkrankheiten (Beta-Versionen) diverser XSLT-Prozessoren noch miterlebt. Jetzt ist er froh, dass XSLT aus dem Schlimmsten draußen ist.