Inhalt:
Donald Knuth' Idee des Literate Programming wurde in den vergangenen Jahren bereits in viele Programmierszenarien, -sprachen usw. übertragen. Auch für SGML/XML wurde die Idee bereits mehrfach diskutiert (vgl. dazu auch die Cover Pages). Gemeinsam ist allen Ansätzen das Folgende:
Dokumentation und Programmcode sind gemeinsam in einer (Quell-)Datei untergebracht.
Eine Software formatiert aus der Quelldatei die Dokumentation im gewünschten Ausgabeformat.
Eine Software extrahiert aus der Quelldatei den lauf- oder compile-fähigen Programmcode.
Während der erste Punkt gewünscht, ja sogar eine zentrale Eigenschaft des Literate Programming ist, und der zweite Punkt üblich, ist der dritte Punkt in den meisten Fällen eine Notwendigkeit, die nicht gewünscht ist. Sie resultiert aus der Tatsache, dass ein Compiler oder Interpreter durch Dokumentation im Programmcode einen Fehler erzeugt. Ein Ansatz, dieses Problem zu lösen, besteht darin, Dokumentation in einer bestimmten Syntax innerhalb von Kommentaren der jeweiligen Programmiersprache unterzubringen.
Im Falle der Programmiersprache XSLT liegt eine besondere Situation vor, falls das Format der Dokumentation ebenfalls eine XML-Sprache ist (etwa im Fall von XHTML oder Docbook): Dann verwenden sowohl die Programmiersprache als auch das Dokumentationsformat die selbe Syntax – nämlich XML. Aus formaler XML-Sicht handelt es sich bei dem Inhalt einer derartigen Datei um nichts weiter als eine XML-Datei, die Elementtypen aus unterschiedlichen Namensräumen verwendet. Um solche Elementtypen auseinanderzuhalten, gibt es eine entsprechende Technik, genannt Namensräume in XML.
Das daraus abgeleitete Konzept des Literate XSLT Programming
ist an folgendem Beispiel veranschaulicht:
Die Dokumentation, hier in Elementen der fiktiven Typen title und para enthalten, ist an beliebigen Stellen im XSLT-Programmcode untergebracht. Die Elemente beider Welten sind durch Namensräume voneinander getrennt. Selbstverständlich ist zur Formatierung eine Software notwendig.
Bei dieser Vorgehensweise sind eine Reihe von Punkten, die im Folgenden diskutiert werden, zu beachten. Die Diskussion führt schließlich zu der Software, die die beschriebene Vorgehensweise implementiert.
Unterhalb des Wurzelelements eines XSLT-Programms sind beliebige Elemente eines fremden Namensraums zulässig, sofern der Namensraum-URI nicht leer ist. Diese Aussage stützt sich auf die entsprechende Festlegung am Ende von Abschnitt 2.2 der XSLT-1.0-Spezifikation (Englisch, Deutsch).
Anders sieht es bei Elementen innerhalb von Templates aus. Diese werden durch die XSLT-Engine als Teil der Ausgabe angesehen. Wünschenswert wäre jedoch die Ignorierung der Dokumentation beim Ablauf des XSLT-Programms. XSLT bietet eine Möglichkeit fremde Elemente innerhalb von Templates nicht als Teil der Ausgabe zu behandeln: Die Elemente müssen als Erweiterungselemente (Englisch, Deutsch) deklariert werden. Das folgende Listing zeigt wie das geht:
Auf den ersten Blick ist der Vorgang sehr einfach: Im Wurzelelement steht xslt:extension-element-prefixes="doc". Damit ist der doc-Namensraum als Erweiterungsnamensraum deklariert, alle entsprechenden Elemente werden nicht als Ausgabe interpretiert. Allerdings geht die XSLT-Engine nun davon aus, dass sie die Erweiterung implementieren müsste; da das für diesen Namensraum natürlich bei keiner Software der Fall ist, bricht die Verarbeitung ohne weitere Vorkehrungen mit einem Fehler ab. XSLT bietet jedoch einen Rückgriff an: Mit xslt:fallback kann der Programmierer einen Ersatz für nicht implementierte Erweiterungen anbieten. In diesem Fall ist xslt:fallback leer, was genau das Verhalten erzeugt, dass wir beim Ablauf des Programms für die eingebettete Dokumentation wünschen: Gar keins.
Zusammenfassung: Die Erläuterungen bis zu diesem Zeitpunkt geben uns die Möglichkeit, Dokumentation in ein XSLT-Programm einzubauen; wobei dies auf der Ebene unmittelbar unter dem Wurzelelement einfach so möglich ist, während für Dokumentation innerhalb von Templates der Namensraum als Erweiterung deklariert und jedes Dokumentationselement einen xslt:fallback besitzen muss.
Der hier vorgestellte Ansatz ist nicht auf ein Dokumentationsformat festgelegt. Es lassen sich prinzipiell Elemente beliebiger Typen ausgeben. Ein beliebtes Format ist XHTML, nicht zuletzt wegen seiner weiten Verbreitung. Aber auch Docbook käme in Frage. Es stellt sich dann die Frage, ob es nicht sinnvoll ist, den Namensraum-URI des jeweiligen Dokumentationsformat für das Präfix doc: zu verwenden.
Das ist aus folgendem Grund nicht möglich: Wenn die Ausgabe, die das XSLT-Programm und die Ausgabe, die das Dokumentationsprogramm erzeugen sollen, beide aus dem selben Namensraum stammen, kann das Dokumentationsprogramm bei seiner Arbeit nicht erkennen, was zur Dokumentation und was zum Programm gehört. Da aber alle für die Dokumentation in Frage kommenden XML-Vokabulare aus offensichtlichen Gründen auch beliebte Ausgabeformate eines XSLT-Programm sind, muss ein generischer Ansatz diesen Sachverhalt berücksichtigen. Aus diesem Grund muss sich die Dokumentation in einem eigenen Namensraum befinden.
Wie sind nun die vorausgehenden Erläuterungen in der Software implementiert? Welche Eigenschaften der Software sind wünschenswert, welche optional?
xsltdoc zeichnet sich durch folgende Eigenschaften aus:
Es gibt keine Festlegung auf ein Dokumentationsformat (XHTML, Docbook usw.).
Bei der Dokumentation besteht nicht die Notwendigkeit, den Dokumentationsnamensraum als Erweiterungsnamensraum zu deklarieren und mit xslt:fallback zu arbeiten. Dies ist nur dann erforderlich, wenn Dokumentation innerhalb von Templates geschrieben werden soll.
Das dokumentierte XSLT-Programm kann unmittelbar durch eine XSLT-Engine ausgeführt werden. Es ist kein Preprocessing notwendig, um das Programm aus der dokumentierten Datei zu extrahieren. Dies ist der wesentliche Unterschied zu klassischen Literate-Programming-Ansätzen, bei denen in je einem Preprocessing-Schritt Dokumentation sowie lauf- und compile-fähiger Code erzeugt wird.
Falls Dokumentation in einem Template gewünscht ist und die Arbeit mit xslt:fallback vermieden werden soll, kann xsltdoc den genannten Preprocessing-Schritt durchführen.
Zusammengefasst implementiert xsltdoc alle diskutierten Ansätze und erlaubt dem Programmierer frei aus den Möglichkeiten zu wählen. Die Tabelle stellt die Möglichkeiten in einer Übersicht dar und zeigt in welchen Fällen das dokumentierte XSLT-Programm direkt lauffähig ist und wann ein Preprocessing durch xsltdoc erforderlich ist.
Entscheidungsmatrix | Erweiterungsnamensraum und xslt:fallbacks | ||
---|---|---|---|
ja | nein | ||
Dokumentation innerhalb von Templates | ja | XSLT-Programm ist direkt lauffähig | Preprocessing durch xsltdoc notwendig |
nein | XSLT-Programm ist direkt lauffähig (Erweiterungsnamensraum und xslt:fallbacks sind nicht erforderlich, wenngleich zulässig) | XSLT-Programm ist direkt lauffähig |
Es bleibt noch die Frage wie xsltdoc unabhängig vom Dokumentationsformat sein kann. Soweit es die doc:-Elemente betrifft ist die Angelegenheit einfach: xsltdoc kopiert die Elemente auf die Ausgabe. Für die xslt:-Elemente ist allerdings eine Umwandlung in das Zielformat zu leisten. Dazu greift xsltdoc auf ein externes Transformationsprogramm zurück. Dieser Teilprozess ist also nicht wirklich unabhängig vom Dokumentationsformat; eine teilweise Unabhängigkeit wurde nur durch Auslagerung des Problems erreicht. Die hier zur Verfügung stehende Referenzimplementierung greift auf xml2html zurück, um die xslt:-Elemente nach XHTML zu transformieren. In diesem Fall muss die Dokumentation auf XHTML basieren. xsltdoc besteht daher aus zwei Teilen:
Die Kernsoftware: xsltdoc.xslt
Ein Teil der abhängig vom Ausgabeformat ist. Bislang ist ausschließlich die Unterstützung für XHTML implementiert: xsltdoc-html.xslt.
Wenn Sie Ihre XSLT-Programme mit xsltdoc dokumentieren und die Dokumentation in XHTML ausgeben möchten, gehen Sie bitte wie folgt vor. Auf der linken Seite der folgenden Tabelle sehen Sie die Beschreibung der einzelnen Schritte; rechts finden Sie die Schritte für ein Beispiel.
Schritt | Beschreibung | Beispiel |
---|---|---|
1 | Ergänzen Sie die xsltdoc-Namensräume in Ihrem XSLT-Programm. |
xmlns:doc="http://www.linkwerk.com/namespaces/2005-02-03/xsltdoc/output/" xmlns:xsltdoc="http://www.linkwerk.com/namespaces/2005-02-03/xsltdoc/" Statt doc und xsltdoc können Sie belibiege andere Präfixe verwenden. |
2 | Schreiben Sie die Programmdokumentation unter Verwendung von XHTML-Elementen. Leiten Sie diese Elemente mit dem Präfix doc: ein. Plazieren Sie Dokumentation zunächst nur außerhalb von Templates. |
<doc:p>erläuternder Text für ein Template</doc:p> |
3 | Optional: Ergänzen Sie bei Bedarf xsltdoc-Elemente, um die Ausgabe zu verfeinern. Eine Beschreibung der xsltdoc-Elemente finden Sie weiter unten. |
Beispiel eines dokumentierten XSLT-Programms, das alle Features benutzt: listing3.xslt |
4 | Formatieren Sie Ihr dokumentiertes XSLT-Programm mit xsltdoc-html.xslt (XHTML-Ausgabe). |
xsltengine -in listing3.xslt -xslt xsltdoc-html.xslt -out listing3.html-param comments drop Die konkrete Aufrufsyntax hängt von der verwendeten XSLT-Engine ab. Der Parameter comments=drop sorgt dafür, dass Kommentare aus dem XSLT-Programm nicht dargestellt werden. Dies ist eine Funktion des zugrundeliegenden xml2html. |
5 | Betrachten Sie das formatierte und dokumentierte XSLT-Programm. |
Die Software ist urheberrechtlich geschützt. Details finden Sie in der Lizenzbeschreibung.
xsltdoc-html.xslt basiert auf xml2html.xslt. Alle drei Dateien sollten in einem Verzeichnis liegen. Beachten Sie, dass xml2html ein CSS zur Formatierung benutzt.
xsltengine -in yourStylesheet.xslt -xslt xsltdoc-html.xslt -out out.html [-param name value]
xsltdoc kennt folgende Parameter:
Mit dem Wert gendoc
erzeugt xsltdoc die Dokumentation. Mit dem
Wert stripdoc
entfernt xsltdoc aus den Eingabedaten alle Dokumentationselemente
und liefert nur das unkommentierte XSLT-Programm als Ausgabe. Das ist geeignet, um
xsltdoc das oben genannte Preprocessing durchführen zu lassen.
xsltdoc verwendet zwei Namensräume: einen für die eingebettete Dokumentation und einen für die nachfolgend beschriebenen Elemente und Attribute, die bei der Formatierung berücksichtigt werden.
Die übliche Deklaration der Namensräume sieht wie folgt aus (die Präfixe sind selbstverständlich frei wählbar):
xmlns:doc="http://www.linkwerk.com/namespaces/2005-02-03/xsltdoc/output/" xmlns:xsltdoc="http://www.linkwerk.com/namespaces/2005-02-03/xsltdoc/"
Generiert in der Dokumentation einen Start-Tag vom Typ X
. Dies ist
nützlich, um die Dokumentation in Abschnitte zu gliedern. Es ist in
XSLT nicht möglich unterhalb des Wurzelelements fremde Containerelemente
für Templates anzulegen. Aus diesem Grund ist es erforderlich, Start- und
End-Tags solcher Container zu Dokumentationszwecken separat zu ergänzen.
Diese Aufgabe erfüllt (für ein Start-Tag) dieses xsltdoc-Element.
Wichtig: Es liegt in der Verantwortung des XSLT-Programmierers
dafür zu sorgen, dass auf diesem Wege erzeugte Start- und End-Tags
zu einer wohlgeformten XML-Ausgabe führen.
Elemente dieses Typs stehen im Inhalt eines xsltdoc:containerstart-Elements
und ergänzen das dort erzeugte Start-Tag um ein Attribut der Form X="Y"
.
Generiert in der Dokumentation einen End-Tag vom Typ X
.
Dieses leere Element, das innerhalb der Dokumentation stehen soll,
erzeugt die Ausgabe des Programmteils dessen xsltdoc:id den Wert X
besitzt.
Ein Attribut dieses Typs dient dazu Teile des XSLT-Programms (z.B. ein Template) mit einer eindeutigen xsltdoc:id zu kennzeichnen.
Falls Sie xsltdoc für ein neues Ausgabeformat erweitern möchten, so
verwenden Sie am besten xsltdoc-html.xslt und xml2html.xslt als Vorlage.
In xsltdoc.xslt gibt es ein Template für /
, den Wurzelknoten des
XPath-Datenmodells. Dort beginnt die Verarbeitung. xsltdoc.xslt ruft dann
das benannte Template mit dem Namen xsltdoc-start
auf. Dies ist in
xsltdoc-html.xslt enthalten und erzeugt den XHTML-Rahmen. Ab dort
findet im wesentlichen eine Verarbeitung gemäß der normalen Verarbeitungsreihenfolge
mittels apply-templates
statt. Alle Elemente aus dem doc- und dem xsltdoc-Namensraum
verarbeitet xsltdoc.xslt. Alle anderen, also alle beliebigen XML-Elemente
transformiert xml2html.xslt nach XHTML.
Auf Wunsch veröffentliche ich Ihre Erweiterungen für neue Ausgabeformate gerne an dieser Stelle; oder ich verlinke Ihre Seiten. Auf meiner Wunschliste stehen FO, Docbook und WordML. Derzeit habe ich keine Pläne, ob/wann ich dies selbst implementieren kann. Um doppelte Arbeit zu vermeiden, schicken Sie mir doch eine Mail, wenn Sie mit der Implementierung beginnen.
Stefan Mintert, $Date: 2005/02/03 17:08:00 $