Die Technik

Dieses Projekt ist nicht nur die Darstellung von "Content", wie redaktionelle Texte, Essays und Prosa heute neudeutsch genannt werden. Ein weiteres Ziel ist die Beschäftigung mit Techniken wie XML unter Einbeziehung von Einzelaspekten wie XSLT, DOM1-3, XPath. Weiterhin dient es für mich als Testplattform für die DOM-Umsetzung in Webbrowsern. Der Zugewinn an Perl-, Python und JavaScript-Kenntnissen ist sicher auch nicht verkehrt.

Der Plan

Die Idee ist, die XML-Quellen möglichst unabhängig von späteren Strukturen speichern zu können und die Bezüge zwischen den einzelnen Texten automatisch auflösen zu können. Es werden dabei drei Ebenen unterschieden: die Speicherung der Texte im Dateisystem, die Verbindungen der Einzeltexte untereinander und die spätere Struktur auf dem Webserver.

Die lokale Speicherung geschieht in eine Verzeichnis pro Kapitel, in das auch die Leser-Kommentare abgelegt werden. Die Struktur, in der diese Kapitel eingebunden ist, wird über eine getrennte XML-Datei festgelegt: zum Zwischenschieben oder Entfernen von Kapiteln ist es so nicht notwendig, die vorherigen oder nachfolgenden Artikel zu ändern. Es werden lediglich Einträge in der Struktur-Dateien hinzugefügt oder entfernt.

Auch wenn die Struktur, wie sie sich dem Betrachter zeigt, baumförmig ist, werden die Artikel auf dem Server in einer flachen Hierarchie (keine Unterverzeichnisse) abgelegt. Dies vereinfacht vor allem den Upload geänderter Texte und die Umstellung auf andere Technologien. (Die erzeugten Namen werden durchaus aus der Baumstruktur der Texte generiert, dies aber nur aus Faulh^w^wzur Vereinfachung der Skripten und um "lesbare" URIs zu erhalten) Weiterhin gibt es keine Extensions (.html, .shtml, .xml, etc), was die Änderung von HTML auf SHTML und von dort auf die Ausgabe eines Servlets sehr vereinfacht hat. Lesenswert zu dem Thema ist übrigens "Cool URIs don't change" von Tim Berners-Lee.

Die Umsetzung

Um aus dieser losen Sammlung von XML-Dokumenten die endgültige Darstellung zu bauen, werden mehrere Scripte benötigt. Zunächst (merge.py) werden die einzelnen Kapitel mit ihren Kommentaren eingelesen, Titel und Kurztitel extrahiert und zusammen mit der Strukturdatei das Inhaltsverzeichnis aufgebaut sowie Referenzen auf das vorherige, nächste und übergeordnete Kapitel eingetragen. In einem Zwischenschritt (makedirectory.py) werden noch fehlende Inhaltsverzeichnis-Seiten generiert. Nun werden die die Referenzen aufgelöst, externe Links, Autor-Hinweise und Stichworte erzeugt (finishxml.py). Mit einem weiteren Script (makedict.py) werden Wörterbuch-Einträge abgeglichen und in einzelne Dateien abgelegt. Die erzeugte XML-Dateien werden dann auf den Server kopiert, wo ein JavaServlet diese beim Aufruf in per XSLT in HTML umsetzt.

Das ganze ist nicht so komplex wie es klingt, aber eine Menge Tipparbeit: die (spärlich kommentierten) Python-Scripte sind insgesamt 1400 Zeilen lang. Insgesamt ist die Python-Implementierung unter Verwendung von pyxml ca. 3 mal langsamer als die vorherige Perl-Implementierung mittels XML::LibXML. Kein Wunder: XML::LibXML ist eigentlich nicht viel mehr als ein Wrapper für libxml2 ein Großteil des Codes läuft dort als C-Kompilat. Pyxml dagegen ist komplett in Python implementiert -- und Python ist für Baumstrukturen wirklich nicht die optimale Sprache.

Fehlschlag: Perl und XML::LibXML

Was hat mich also zur Umstellung von Perl auf Python bewogen? Eigentlich wären die Perl-Bindings zu libxml2 optimal, ja wenn sowohl die Bindings wie auch libxml2 selbst nicht so schrecklich instabil wären -- mit jeder Versionsänderung an einer der beteiligten Komponenten libxml2, Perl und XML::LibXML sind zwar einige der zahlreichen alten Bugs gefixt, aber dafür haben sich gleich genausoviele neue Abgründe aufgetan. Insbesondere das neue UTF-8-Handling von Perl 5.8 scheint sich mit dem XML-Modul zu beissen... Aktuell fliegt mir das Modul aber mit einem "unknown error due XInclude at .../LibXML.pm line 340" um die Ohren. Zwar immer noch besser als die kommentarlosen Abstürze und fehlerhaft eingelesener Dateien vorheriger Versionen, den Grund gefunden habe ich aber trotzdem nicht (<xi:xinclude> auf Testdateien, auch verschachtelt, funktioniert natürlich anstandslos.)

Verworfen: Java und Xerces

Eine Alternative zu Python wäre Java gewesen, aber die DOM-Implementierung von Xerces unterstützt per Default nur DOM1 und DOM2, ich benötige jedoch einige DOM3-Features, die dort nur mit Neubau der Library verfügbar sind (unter einem anderen Namespace) und jede Menge Handarbeit benötigen (zumindest als ich mir das zuletzt angesehen habe). Abgesehen davon mag das Design der Java-Implementierung zwar sehr sauber sein, für eine brauchbare Anwendung ist das aber viel zu komplex. Ob da wohl die selben Leute hinter stecken, die damals Xlib entworfen haben?

Die Lösung: Python und pyxml

Welch Wohltat dagegen die Python-Implementierung! (Fast) alles was ich brauche ist in pyxml vorhanden (bis auf XInclude, aber das war schnell nachgebaut), die Umsetzung von Perl auf Python konnte fast 1:1 geschehen und bestand fast ausschließlich aus Tipparbeit, das Resultat sieht auch noch eleganter aus. Und vor allem: keine bösen Überraschungen. Da verschmerze ich auch den Einbruch an Performance -- ist ja zum Glück alles off-line. Portierungsaufwand, inklusive Python-Grundlagen lernen: 5 MT. So gehört das!