19.2 XSL  
Die eXtensible Stylesheet Language (XSL) ist ein Standard des W3C, XML-Daten in ein (mehr oder minder) beliebiges Ausgabeformat umzuwandeln – im Web natürlich zumeist in HTML. Und mit JavaScript gibt es eine Möglichkeit, im Browser eine XSL-Transformation (XSLT) durchzuführen – zumindest in den meisten Browsern, aber wieder mit erheblichen Unterschieden.
Hier zunächst eine XSL-Datei, die die (bereits bekannte) XML-Daten in (bereits bekanntes) HTML-Markup für eine Aufzählungsliste umwandelt:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:template match="/">
<ul>
<xsl:for-each select="links/link">
<li><a><xsl:attribute name="href">
<xsl:value-of select="url" />
</xsl:attribute><xsl:value-of select="text" /></a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
So weit, so gut. Jetzt wird es leider wieder browserspezifisch. Beginnen wir diesmal mit dem Internet Explorer, der wieder fleißig auf ActiveX setzt. Sie benötigen zwei ActiveX-Objekte:
|
MSXML2.FreeThreadedDOMDocument – zum Laden des XSL-Dokuments (das ja ebenfalls ein XML-Dokument ist) |
|
MSXML2.XSLTemplate – zur Durchführung der XSL-Transformation |
Beginnen wir mit dem Laden des XML-Dokuments: Die Methode load() lädt ein Dokument, allerdings asynchron, was im vorliegenden Beispiel eine zweite Callback-Methode erfordern würde. Deswegen ist es besser, das Dokument synchron zu laden, indem Sie die Objekteigenschaft async auf false setzen:
var xsl = new ActiveXObject("MSXML2.FreeThreadedDOMDocument");
xsl.async = false;
xsl.load("links.xsl");
In Mozilla-Browsern verwenden Sie die Methode document.implementation.createDocument(), die ein DOM-Dokument erzeugt. Der Clou: Dieses Dokument besitzt dann eine Methode load(), mit der Sie Dateien laden können. Beachten Sie, dass Sie hier wie beim XMLHttpRequest-Objekt auch die aktuelle Domain nicht verlassen dürfen.
var xsl = document.implementation.createDocument("", "", null);
xsl.async = false;
xsl.load("links.xsl");
Doch damit nicht genug der Browserunterschiede; auch die XSL-Transformation läuft unterschiedlich. Der Internet Explorer setzt auf das bereits zuvor erwähnte ActiveX-Objekt MSXML2.XSLTemplate; in dessen Eigenschaft stylesheet geben Sie die zuvor geladene XSL-Datei an:
var template = new ActiveXObject("MSXML2.XSLTemplate");
template.stylesheet = xsl;
Mit der Methode createProcessor() wird ein Verarbeitungsobjekt erzeugt, das die Transformation durchführen kann: Sie müssen dieses Objekt dann nur noch mit Daten füttern: Die Eigenschaft input erwartet das zu transformierende XML, und zwar als XML-DOM-Objekt. Dann startet transform() die Transformation.
var process = template.createProcessor();
process.input = daten;
process.transform();
Abschließend geben Sie die Rückgabe (sie steht in der Eigenschaft output) einfach aus beziehungsweise hängen sie in den DOM-Baum ein.
var div = document.createElement("div");
div.innerHTML = process.output;
document.body.appendChild(div);
Das Vorgehen in Mozilla-Browsern (und ab Version 9 auch im Opera) ist vom Prinzip her ähnlich, von der Durchführung und den Bezeichnern aber vollkommen unterschiedlich. Die Klasse für das Verarbeitungsobjekt heißt XSLTProcessor(), die Methode zum Laden der XLS-Datei ist importStylesheet(), und die Methode zur Transformation hört auf den Namen transformToFragment() (und erwartet als zweiten Parameter eine Referenz auf das aktuelle HTML-DOM). Dann aber können Sie per appendChild() die Rückgabe von transformToFragment() direkt in das aktuelle Dokument einfügen:
var process = new XSLTProcessor();
process.importStylesheet(xsl);
var ergebnis = process.transformToFragment(
daten, document);
document.body.appendChild(ergebnis);
Das mag sich jetzt sehr aufwändig anhören und ist es gewissermaßen auch, aber wenn Sie das einmal implementiert haben (oder einfach den Code von der Buch-DVD verwenden), können Sie das Prinzip immer und immer wieder anwenden. Hier noch einmal der komplette Code, inklusive Browserabfrage:
<html>
<head>
<title>AJAX</title>
<script type="text/javascript"><!--
var http = null;
if (window.XMLHttpRequest) {
http = new XMLHttpRequest();
} else if (window.ActiveXObject) {
http = new ActiveXObject("Microsoft.XMLHTTP");
}
window.onload = function() {
if (http != null) {
http.open("GET", "links.xml", true);
http.onreadystatechange = ausgeben;
http.send(null);
}
}
function ausgeben() {
if (http.readyState == 4) {
var daten = http.responseXML;
if (window.ActiveXObject) {
var xsl = new ActiveXObject("MSXML2.FreeThreadedDOMDocument");
xsl.async = false;
xsl.load("links.xsl");
var template = new ActiveXObject("MSXML2.XSLTemplate");
template.stylesheet = xsl;
var process = template.createProcessor();
process.input = daten;
process.transform();
var div = document.createElement("div");
div.innerHTML = process.output;
document.body.appendChild(div);
} else if (window.XSLTProcessor) {
var xsl = document.implementation.createDocument("", "", null);
xsl.async = false;
xsl.load("links.xsl");
var process = new XSLTProcessor();
process.importStylesheet(xsl);
var ergebnis = process.transformToFragment(
daten, document);
document.body.appendChild(ergebnis);
}
}
}
//--></script>
</head>
<body>
</body>
</html>
|