Writing Code and Other Prose

A blog about software development, electronics, and writing.

XML in der Praxis

Bei ihrer Einführung wurde die eXtensible Markup Language (XML) von vielen Seiten begrüßt, da ein Standard, mit dem sich Daten plattformunabhängig beschreiben und kodieren lassen, zu diesem Zeitpunkt längst überfällig war. Jetzt ist die anfängliche Euphorie vorbei, XML ist etabliert und sollte im Werkzeugkasten eines jeden Softwareentwicklers zu finden sein.

Doch obwohl XML in vielen Belangen durch seine Einfachheit besticht, ist es im Detail recht komplex und beinhaltet eine Menge Fallstricke. Daher habe ich ein paar Regeln zusammengestellt, die sich in meiner täglichen Arbeit bewährt haben.

Verwende XML konsequent

Oft sehe ich mich mit XML-Dokumenten konfrontiert, die noch weitere Kodierungen enthalten:

<!--
Das Attribut dim enthält eine durch Kommata
getrennte Liste mit den Elementen Höhe, Breite und Tiefe:
-->

<kasten dim="1,2,3"/>

Das ist nicht im Sinne des Erfinders und wir wissen alle, dass wir den obigen Kommentar in der realen Welt nicht finden würden und auf unsere Rate- und Interpretationskunst angewiesen wären, um rauszubekommen, wie die Zahlenliste 1,2,3 zu interpretieren ist.

Abgesehen davon, dass ein solches Dokument nicht selbsterklärend ist, hat es den Nachteil, dass wir den Inhalt des Attributs dim separat verarbeiten müssen. Zwar ist die Zerlegung einer kommaseparierten Liste mit den meisten Programmiersprachen einfach zu bewerkstelligen, jedoch entsteht hier eine unnötige Fehlerquelle.

Eine bessere Repräsentation ist die folgende:

<kasten hoehe="1" breite="2" tiefe="3"/>

Hier erübrigt sich jeglicher Kommentar und die Software, die ein solches Dokument auswertet, ist auch deutlich übersichtlicher. Noch besser wird unser kasten-Element, wenn wir ein Attribut für die Einheit spendieren, in der die Dimensionen unseres Kastens angegeben werden:

<kasten einheit="cm" hoehe="1" breite="2" tiefe="3"/>

Der Einsatz von CSV (Comma Separated Values) in XML-Dokumenten ist vergleichsweise harmlos und ich habe schon deutlich Schlimmeres gesehen, wie z. B. die Speicherung von binär kodierten Festkommazahlen, die Byte für Byte aneinandergehängt und anschließend mittels Base64 kodiert wurden. So etwas führt die Entwurfskriterien von XML ad absurdum, denn der Charme von XML liegt nicht zuletzt darin begründet, dass es plattformunabhängig ist und Programmierer sich eben keine Gedanken darüber machen müssen, in welcher Reihenfolge ein bestimmter Prozessor Daten im Speicher ablegt bzw. adressiert.

Aufgrund seiner Natur eignet sich XML ohnehin nur bedingt zur Speicherung von binären Daten. Um genau zu sein: Rein binäre Daten lassen sich mit XML überhaupt nicht repräsentieren, sondern sie müssen zuvor in ein Textformat, wie z. B. Base64, umgewandelt werden. Das kann selbstverständlich notwendig sein, um Bilder oder Audiodateien zu übertragen, aber man sollte sich in solchen Fällen immer fragen, ob XML eine vernünftige Wahl ist.

So habe ich sogar schon gesehen, das ganze GIF-Dateien im Base64-Format in XML-Kommentaren übertragen wurden. Die Begründung dafür war, dass Kommentare vom XML-Parser nicht verarbeitet werden und das Programm somit viel schneller laufe. Eine solche Vorgehensweise ist mehr als nur fragwürdig.

Verwende vernünftige Element- und Attributnamen

Zuallererst bedeutet das: VERWENDE KLEINSCHREIBUNG! Nicht nur, dass es ein wenig altbacken wirkt, lediglich auf Großbuchstaben zurückzugreifen, es ist auch schlechter lesbar und editierbar. Mittlerweile bin ich dazu übergegangen, ausschließlich Kleinbuchstaben zu verwenden und Wörter gegebenenfalls durch Bindestriche zu trennen. Anstatt ELEMENTNAME, ElementName oder elementName, verwende ich element-name.

Der aktuelle XML-Standard sieht die Verwendung von beliebigen Unicodezeichen in Element- und Attributnamen vor. Aus Gründen der Kompatibilität mit bestehender Software ist es aber ratsam, bei den üblichen ASCII-Zeichen ‘a-z’, ‘A-Z’, ‘0-9’ und ‘-’ zu bleiben. Ferner sind Unicode-Editoren noch nicht sehr weit verbreitet.

XML-Dokumente enthalten häufig Listen und daher ist es eine gute Idee, eine Konvention für die Benennung von Listenelementen festzulegen und zu befolgen. Bei mir sieht das folgendermaßen aus:

<punkte>
  <punkt x='5' y='7'/>
  <punkt x='9' y='1.5'/>
</punkte>

Natürlich geht es auch so:

<punkt-liste>
  <punkt x='5' y='7'/>
  <punkt x='9' y='1.5'/>
</punkt-liste>

Keinesfalls ist es sinnvoll, Elementnamen durchzunummerieren:

<punkt1 x='5' y='7'/>
<punkt2 x='9' y='1.5'/>

Mache dir klar, wie Zeichen kodiert werden

Viele Programmierer waren durch die Verwendung von XML zum ersten Mal gezwungen, sich eingehender mit der Kodierung von Zeichen, insbesondere mit Unicode, zu befassen. Wer nicht weiß, was Unicode ist und wie er funktioniert, der sollte unbedingt Joel Spolskys Artikel The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode And Character Sets (No Excuses!) lesen. Für die Arbeit mit XML ist es enorm wichtig, die Kodierung von Zeichen bis ins Detail verstanden zu haben!

Die häufigsten Missverständnisse gibt es meiner Erfahrung nach in Bezug auf die voreingestellte Kodierung von XML-Dokumenten, nämlich UTF-8. Wird im Prolog eines XML-Dokumentes keine Zeichenkodierung mittels des Attributs encoding angegeben, so erwartet der XML-Parser, dass alle dem Prolog folgenden Zeichen im Format UTF-8 kodiert sind.

Wird das folgende Beispielprogramm mit einem Texteditor eingegeben, der Zeichen im Format ISO-8859-1 speichert, so wird ein XML-Parser das Dokument fehlinterpretieren:

<?xml version='1.0'>
<umlaute>äöüß</umlaute>

Erst wenn die Kodierung der nachfolgenden Zeichen angegeben wird, klappt alles reibungslos:

<?xml version='1.0' encoding='iso-8859-1'>
<umlaute>äöüß</umlaute>

Es ist wichtig, sich im Vorfeld Gedanken darüber zu machen, welche Kodierung für ein neues XML-Dokument verwendet werden soll. Soll das Dokument beispielsweise häufig per Hand mit herkömmlichen Texteditoren editiert werden, so ist es im Normalfall sinnvoll, die Kodierung ISO-8859-1 einzustellen.

Bevorzuge Attribute gegenüber Elementen

Viele halten es für eine Frage der Ästhetik oder des Geschmacks, ob bestimmte Werte innerhalb eines XML-Dokuments mit Elementen oder mit Attributen repräsentiert werden. Ich denke, dass Attribute gegenüber Elementen häufig Vorteile haben.

Unser kasten-Beispiel würde unter Verwendung von Elementen anstatt von Attributen folgendermaßen aussehen:

<kasten>
  <einhei>cm</einheit>
  <hoehe>1</hoehe>
  <breite>2</breite>
  <tiefe>3</tiefe>
</kasten>

Ganz offensichtlich ist die Variante, die Elemente verwendet, deutlich länger und weniger übersichlich, denn die eigentliche Information, die transportiert wird, ist nur schwer zu erkennen. Die mangelnde Übersicht resultiert in erster Linie daraus, dass Elementnamen wiederholt werden und wie in beinahe jedem Bereich der Softwareentwicklung ist Redundanz auch hier eine schlechte Sache.

Es gibt aber noch weitere Nachteile, wie die Bedeutung von nicht-sichtbaren Zeichen. Bei Attributen ist es offensichtlich, dass Werte wie “ hallo ” und “hallo” unterschiedlich sind. Doch wie verhält es sich bei Elementen? Welchen Wert hat das Element text im folgenden Beispiel?

<text>
  Hallo,

Welt!  </text>

Die Repräsentation von nicht-sichtbaren Zeichen ist jedoch gleichzeitig eines der wenigen Argumente für Elemente, d. h., wenn Werte dargestellt werden müssen, die Zeilenumbrüche, vertikale Tabulatoren u. ä. enthalten, muss man auf Elemente zurückgreifen.

Ein letzter Vorteil der Verwendung von Attributen ist Geschwindigkeit, denn Attribute führen nicht nur zu kürzeren Dokumenten, sondern erhöhen die Performanz aufgrund der Art und Weise, wie XML-Dokumente im Normalfall verarbeitet werden. So gut wie alle Parser greifen direkt oder indirekt auf die SAX2-API zurück. Diese sieht vor, dass für jedes Element eines XML-Dokuments eine Funktion namens startElement aufgerufen wird, der als Parameter der Name des Elements und eine Liste seiner Attribute übergeben werden. Mehr Elemente führen also automatisch zu mehr Funktionsaufrufen und die sind im Regelfall teuer. Besonders in den meisten objektorientierten Programmiersprachen.

Vermeide Präsentationselemente in XML-Dokumenten

XML-Dokumente sollten nur Daten in strukturierter Form enthalten und keinerlei Informationen darüber, wie diese gegebenenfalls präsentiert werden sollen. Die einzige Ausnahme, die ich in diesem Zusammenhang sehe, ist die Reihenfolge von Elementen, d. h., Elemente, die in einer bestimmten Reihenfolge präsentiert werden sollen, können in einem XML-Dokument in eben dieser Reihenfolge gespeichert werden.

Konsequent wird diese Regel in XHTML und den dazugehörigen Cascading Style Sheets umgesetzt. Anstatt wie früher einen wichtigen Satz für alle Ewigkeit mit schrillen Farben und fetter Schrift zu präsentieren, wird derselbe Satz nun mit der Eigenschaft “wichtig” attributiert und kann dann von jedem Client mittels verschiedener Style Sheets entsprechend präsentiert werden. Beispielsweise kann eine Anwendung, die über eine synthetische Spracherzeugung verfügt, den Satz etwas lauter sprechen.

Verwende einen XML-Parser

Diese Regel mag banal bis selbstverständlich klingen, aber es gibt immer noch Programmierer, die der Versuchung erliegen, einem XML-Dokument mit Zeichenkettenfunktionen wie indexOf und regulären Ausdrücken auf den Leib zu rücken.

Dieser Ansatz hat so viele Nachteile, dass ich gar nicht weiß, wo ich anfangen soll. Zum einen ist die Verarbeitung von Zeichenketten per Hand immer eine knifflige und fehleranfällige Sache, die nicht selten zu unübersichtlichen Programmen führt. Des weiteren kann eine handgeschriebene Lösung niemals einen vollwertigen XML-Parser auch nur im Ansatz ersetzen. Wer es nicht glaubt, der werfe mal einen Blick auf eine entsprechende Implementierung, wie z. B. das Xerces-Projekt.

Das wichtigste Argument aber ist: Die Verwendung eines XML-Parsers ist eine einfache Sache. Für so gut wie jede moderne Programmiersprache gibt es mittlerweile XML-Parser, deren Verwendung sich häufig auf den Aufruf einer Methode namens parse reduziert.

Nicht selten höre ich die Argumentation, der Einsatz eines XML-Parsers wäre nicht performant genug. Mal abgesehen davon, dass diese Behauptung in den meisten Fällen schlichtweg falsch ist, bedeutet diese Argumentation in letzter Konsequenz doch, dass XML in diesem Fall gar nicht hätte eingesetzt werden dürfen.

Vermeide die direkte Verwendung der DOM-API

Das Document Object Model (DOM) definiert eine allgemeine (Speicher-)Repräsentation von XML-Dokumenten, die in jeder Programmiersprache leicht umsetzbar sein sollte. Egal, ob in Java, C++ oder COBOL, der Zugriff auf die einzelnen Knoten eines XML-Dokumentes soll immer gleich aussehen.

Im Grundsatz ist das eine gute Idee, doch in der Realität erwies sich das Vorhaben als Flop. Moderne Programmiersprachen wie Java oder Ruby verfügen über völlig andere Mittel als das alte Schlachtross COBOL und es ist absolut sinnvoll, sich diese zu Nutze zu machen.

Sowohl zur Verarbeitung als auch zur Erzeugung bietet es sich also an, entsprechende Klassenbibliotheken zu verwenden. In Java ist das z. B. JDOM und in Ruby ist es REXML.

Wer keine weitere Klassenbibliothek suchen bzw. verwenden möchte oder kann, der ist - zumindest was die Verarbeitung von XML-Dokumenten angeht - mit der XPath-API gut beraten. Sie ist ein etablierter Standard und wird mittlerweile von vielen XML-Parsern bzw. XSLT-Prozessoren implementiert.

Erzeuge XML-Dokumente nicht mittels Zeichenketten

Ich muss gestehen, dass auch ich früher oft der Versuchung erlag, XML-Dokumente “mal eben” mittels Zeichenketten zu erzeugen. Nachdem ich aber mit diesem vermeintlich einfachen Ansatz mehrfach Schiffbruch erlitten habe, verwende ich selbst zur Erzeugung kleiner Dokumente entsprechende Klassenbibliotheken.

Die gravierendsten Nachteile bei der Erzeugung von XML-Dokumenten mittels Zeichenketten sind:

  • Die manuelle Kodierung von XML-Sonderzeichen
  • Die nicht-transparente Kodierung von Zeichen
  • Die eingeschränkte Weiterverarbeitung von XML-Fragmenten innerhalb des Programms

XML definiert die Sonderzeichen <, >, “, ‘ und &. Diese dürfen in Element- und Attributwerten nicht direkt verwendet werden, sondern müssen durch die Entitäten lt, gt, quot, apos und amp ersetzt werden. Baut man XML-Dokumente mit Zeichenketten auf, so ist an jeder Stelle sicherzustellen, dass diese Ersetzung stattfindet, was zu einer Durchsetzung des Programms mit Funktionsaufrufen wie encodeMarkup, toMarkup o. ä. führt.

An jeder Stelle des Programms ist sicherzustellen, dass die Zeichen des zu erzeugenden XML-Dokuments dieselbe Kodierung haben und dass diese Kodierung im Prolog des Dokuments angegeben wird. Stammen Teile des Dokuments aus externen Quellen, wie z. B. aus einer Datei oder einer Datenbank, so kann dies eine recht knifflige Aufgabe werden. Die meisten Klassenbibliotheken zur Erzeugung von XML-Dokumenten enthalten daher sog. Transcoder-Klassen, die eine Konvertierung von einer Zeichenkodierung in eine andere transparent erledigen.

Wird ein XML-Dokument bzw. -Fragment als Zeichenkette (und nicht als DOM o. ä.) repräsentiert, so kann es nur stark eingeschränkt weiterverwendet werden. Beispielsweise ist es nur mit viel Aufwand möglich, Elemente oder Attribute hinzuzufügen, zu verändern oder zu entfernen. Dies macht ein Programm schnell unflexibel.

Zusammenfassend lässt sich sagen, dass durch die Verwendung von Zeichenketten zur Erzeugung von XML-Dokumenten schnell Dokumente entstehen, die nicht wohlgeformt sind und dass Programmteile, die größere Textblöcke erzeugen, in vielen Programmiersprachen dazu neigen, unflexibel und unübersichtlich zu werden. Ferner ist die Erzeugung von XML-Dokumenten mit entsprechenden Klassenbibliotheken zumeist genauso einfach, wie das Zusammenfügen von Textfragmenten.

XML allein reicht nicht

Rund um XML ist mittlerweile ein ganzer Zoo von weiteren Technologien und Standards entstanden. An vorderster Front stehen die verschiedenen Möglichkeiten zur Beschreibung von XML-Dokumenten, nämlich Document Type Defintion (DTD), XmlSchema und RelaxNG. Aber auch XPath, XLink und XPointer sind wichtig.

Eine effiziente Verwendung von XML ist ohne diese Technologien oft nicht möglich und jeder Entwickler sollte zumindest wissen, dass es sie gibt und wozu sie gut sind.

Es muss nicht immer XML sein

Meiner Meinung nach wird XML heute zu oft eingesetzt, weil sich Entwickler nicht die Mühe machen wollen, einen eigenen Parser für ein Alternativformat zu schreiben. Das ist im Grundsatz vernünftig, aber dabei darf nicht vergessen werden, dass es durchaus andere Formate und die dafür notwendigen Parser gibt. Beispiele sind u. a. YAML, OGDL und die guten alten Properties-Dateien.

Des weiteren ist XML oft keine adäquate Repräsentation. XSL ist ein abschreckendes Beispiel dafür, wo man XML besser nicht einsetzt, nämlich als Beschreibung von Programmiersprachen und auch die Eingabedateien von Ant veranschaulichen eindrucksvoll, welche Folgen der übereilte Einsatz von XML haben kann. Selbst James Duncan Davidson, der ursprüngliche Entwickler von Ant, bereut heute seine Entscheidung für XML.

Als Faustregel sollte gelten, dass XML-Dokumente im Idealfall von Maschinen und nicht von Menschen gelesen oder gar editiert werden.

Comment by Anonymous on 2004-10-12 15:59:23:

Hi Maik,

danke für die Tipps. Wobei mir einige schon immer eingeleuchtet haben. Wo ich beim Thema bin.

Sollte eine Dokumentation in DocBook geschriben werden, wobei die DTD sich alle Nase lang ändert und ich bis dato keine IDE gefunden habe, also alles mit XMLSPY schreiben muß ? Macht das Sinn, wenn eh alles nach Word /PDF geXSLT wird ?

Gruß Michael.

Comment by Maik on 2004-10-12 18:58:20:

@Michael: Meiner Meinung nach ist DocBook ein Paradebeispiel dafür, dass XML sich nicht zur Editierung durch Menschenhand eignet. Wenn du aus irgendeinem Prozess heraus DocBook-Dokumente erzeugst, die du dann mittels verschiedener Stylesheets in unterschiedliche Formate (PDF, RTF etc.) wandelst, dann ist das eine nützliche Sache. Ansonsten würde ich im wahrsten Sinne des Wortes die Finger davon lassen. Insbesondere, weil die Unterstützung durch entsprechende Editoren wirklich dürftig ist.

Comment by Anonymous on 2004-10-13 08:37:43:

Mein Kompliment, ein strukturierter und informativer Artikel. Ein interessantes Thema bei dem ich (auch als Nicht-Programmierer) wieder mal etwas gelernt habe. Vor allem der Link zu der Seite von Joel Spolsky ist bereits in meinen Bookmarks verewigt. Davon lese ich gerne mehr…

Viele Grüße Sandras Admin


Share

comments powered by Disqus