Bevor wir uns das Skript ansehen, ein kurzer Blick auf ein Beispieldokument. Das folgende Listing zeigt einen Ausschnitt aus einer Bundesliga-Tabelle, die mit XML-Auszeichnungen versehen ist. Es handelt sich um eine gültige Instanz mit eingebetteter DTD.
<?stylesheet href="liga.dsl" type="text/dsssl"?> <?xml version="1.0" standalone="yes" encoding="ISO-8859-1"?> <!DOCTYPE liga [ <!ELEMENT liga (pos+) > <!ELEMENT pos (verein, punkte, tore) > <!ELEMENT verein (#PCDATA) > <!ELEMENT punkte (#PCDATA) > <!ELEMENT tore (#PCDATA) > ]> <liga> <pos> <verein>Kaiserslautern</verein> <punkte>45</punkte> <tore>+17</tore> </pos> <pos> <verein>B. München</verein> <punkte>41</punkte> <tore>+18</tore> </pos> <!-- hier stehen noch mehr Vereine --> <pos> <verein>VfL Bochum</verein> <punkte>20</punkte> <tore>-9</tore> </pos> <pos> <verein>1. FC Köln</verein> <punkte>20</punkte> <tore>-13</tore> </pos> </liga>
Die erste Zeile ist hier der interessante Teil. Diese Processing Instruction stellt die Verbindung mit einem DSSSL-Stylesheet her, und zwar in einer Form, die James Clarks DSSSL-Maschine Jade versteht. Hier muss man sagen, dass es sich um eine proprietäre Regelung handelt. Die offizielle, vom W3C abgesegnete Variante (siehe Anhang B ) sieht zum Beispiel so aus:
<?xml-stylesheet href="htmltoc.xsl" type="text/xsl"?>
Der xmlhandler soll natürlich mit verschiedenen Stylesheets umgehen können. Das CGI-Skript muss daher selbstständig ermitteln, welches Stylesheet und welcher Prozessor benötigt werden. Im nächsten Listing (ein Bourne-Shell-Skript) ist dies als Schritt 2 zu erkennen. An dieser Stelle sei erwähnt, dass wir nachfolgende Beispiele unter Unix (genauer Solaris 2) getestet haben.
#!/bin/sh # # XML-Handler - Wrapper zur Umwandlung von XML in HTML mit XSL oder DSSSL # PATH=/usr/bin/:/app/unido-inf/sun4_55/jdk/1.1.6/bin/:${PATH} export PATH # # Konfiguration fuer Jade und XT # JADEBIN=/app/unido-inf/sun4_55/jade/1.2.1/bin/jade CATALOG=/app/unido-inf/sun4_55/jade/1.2.1/dsssl/catalog CLASSPATH=/app/unido-inf/sun4_55/xp/0.5:/app/unido-inf/sun4_55/xp/0.5/xp.jar:/app/unido-inf/sun4_55/xt/19990514/xt.jar:/app/unido-inf/sun4_55/xt/19990514/sax.jar:/app/unido-inf/sun4_55/jdk/1.1.6/lib/classes.zip:${CLASSPATH} export CLASSPATH # # XTWRAPPER ist ein Shell-Skript, das den Aufruf von java mit # den notwendigen Klassen und Parametern regelt XTWRAPPER=/app/unido-inf/sun4_55/xt/19990514/bin/xt JDKHOME=/app/unido-inf/sun4_55/jdk/1.1.6 export JDKHOME JAVA_HOME=/app/unido-inf/sun4_55/jdk/1.1.6 export JAVA_HOME # # 1) Name der XML-Datei # XMLDATEI=${PATH_TRANSLATED} # # 2) Herausfinden, welchen MIME-Typ das zugehoerige StyleSheet verwendet # StyleSheetMIME=`grep stylesheet ${XMLDATEI} | sed 's/.*type="\([^\"]*\)".*/\1/'` if [ "${StyleSheetMIME}" = "text/dsssl" ] then # # 3) Bei DSSSL-StyleSheets unmittelbar Jade aufrufen # # # HTTP-Header: # echo "Content-type: text/html" echo ${JADEBIN} -c ${CATALOG} -t sgml ${XMLDATEI} # # abschliessendes LF, weil Jade es unterdrueckt echo exit else if [ "${StyleSheetMIME}" = "text/xsl" ] then # # 4) Falls der Browser XSL beherrscht, keine Transformation durchfuehren # ACCEPT=`echo ${HTTP_ACCEPT} | sed 's|.*\(text/xsl\).*|\1|'` if [ "${ACCEPT}" = "text/xsl" ] then # # HTTP-Header: # echo "Content-type: text/xml" echo cat ${XMLDATEI} else # # HTTP-Header: # echo "Content-type: text/html" echo # # 5) Transformieren: zuerst den Namen des XSLT-StyleSheets ermitteln # XSLSS=`grep stylesheet ${XMLDATEI} | sed 's/.*href="\([^\"]*\)".*/\1/'` DIRECTORY=`echo ${XMLDATEI} | sed 's|^\(.*/\)[^/]*$|\1|'` cd ${DIRECTORY} ${XTWRAPPER} ${XMLDATEI} ${XSLSS} fi exit else echo "<h1>Interner Fehler</h1><h2>${StyleSheetMIME}</h2>" fi fi
Der erste Teil des Skripts dient nur der Konfiguration des
XSLT-Programms XT und des DSSSL-Programms Jade, beide stammen aus
der Feder von James Clark. Als erste Aktion (1) stellt das Skript
den Dateinamen der XML-Datei fest. Dieser ist in
der CGI-Variablen PATH_TRANSLATED zu finden.
Schritt (2) sucht die Stylesheet-Processing-Instruction und
extrahiert mit Hilfe des sedDer
stream
editor
steht praktisch in jeder Unix-Variante zur
Verfügung. den MIME-Typ (hier
text/xsl oder text/dsssl). Von nun an
gliedert sich das Skript in jeweils einen Block für jeden
unterstützten Stylesheet-Typ. Im Fall eines DSSSL-Stylesheets wird
unmittelbar die Transformation in HTML mit Jade aktiviert (Jade
findet das Stylesheet selbstständig und benötigt dafür keinen Parameter). Etwas
anderes als die Transformation ist nicht möglich, da kein bekannter Browser DSSSL
beherrscht. Im Fall von XSL kann es sein, dass der Browser damit
umgehen kann. Deshalb prüft das Skript in Punkt (4) den Inhalt der
Variablen HTTP_ACCEPT. Findet sich darin der Eintrag
text/xsl, so kann die XML-Datei ohne Umwandlung
ausgeliefert werden. An dieser Stelle sei noch erwähnt, dass man sich
bei dieser Content-Negotiation nicht unbedingt auf den Browser
verlassen kann. So schickt der Navigator schon seit mehreren
Versionen als akzeptierten MIME-Typ die Zeichenkette
*/*. Da diese Angabe nicht wörtlich zu nehmen ist,
erfolgt hier die explizite Prüfung auf text/xsl. Falls
der Browser XSL nicht beherrscht, transformiert das Skript wie
zuvor von XML in HTML, diesmal unter Beihilfe von XT (5). Andere
Fälle sollten nicht vorkommen, der letzte else-Zweig des Skriptes
ist nur als exemplarische Fehlermeldung zu verstehen, die anzeigt,
dass ein unbekannter Stylesheet-Typ gefunden wurde.
Die wesentlichen Teile sind damit bereits fertig gestellt. Aber das Beispiel des oben gezeigten XML-Dokuments ist ohne Stylesheet noch nicht komplett. Das zugehörige DSSSL-Programm ist im folgenden Listing zu finden.
<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN"> (declare-flow-object-class element "UNREGISTERED::James Clark//Flow Object Class::element") (element liga (make element gi: "table" attributes: (cons (list "border" "1") '()) (make element gi: "tr" ; Kopfzeile der Tabelle (make sequence (make element gi: "th" (literal "Mannschaft")) (make element gi: "th" (literal "Punkte")) (make element gi: "th" (literal "Tor-Verhältnis")))) (process-children))) ; Inhalt der Tabelle (element pos (make element gi: "tr")) (element verein (make element gi: "td")) (element punkte (make element gi: "td")) (element tore (make element gi: "td"))
Lädt man nun die Datei beispiel.xml, so zeigt der Browser die Ansicht in Abbildung 64, also eine Transformation der XML-Datei in eine HTML-Tabelle.
Das Beispiel der Bundesliga-Tabelle enthält ein ganz einfaches Dokument, eben nur eine Tabelle. Es ist absichtlich schlicht gewählt, weil es hier nicht um die Komplexität von XML-Dokumenten gehen soll, sondern nur um die serverseitige Behandlung. Um aber doch noch ein etwas umfangreicheres Beispiel zu zeigen, bietet sich die Konvertierung von HTML in HTML an. Zunächst erscheint das vielleicht sinnlos, aber die folgende Anwendung verdeutlicht den Zweck.