Ein paar Gedanken zu XML

Die Extensible Markup Language (engl. für „erweiterbare Auszeichnungssprache“), abgekürzt XML, ist eine Auszeichnungssprache zur Darstellung hierarchisch strukturierter Daten in Form von Textdateien. XML wird u. a. für den Austausch von Daten zwischen Computersystemen eingesetzt, speziell über das Internet.

Soweit Wikipedia. Aus irgendeinem Grund entschloss ich mich einst, eine Vorlesung zu dem Thema zu besuchen. Das war auch eine gute Idee, ich kam mit vielem in Berührung, was ich wohl sonst niemals freiwillig verwendet hätte. Nun, ich war zugegebenermaßen schon immer ziemlich skeptisch, aber auch ziemlich aufgeschlossen gegenüber XML. Und in der Tat, der Grundgedanke von XML ist, soweit ich denke ihn zu verstehen, garnicht so schlecht. Eine Syntax zur Definition von Bäumen und allgemein Graphen, zur allgemeinen Definition von Datensätzen, zum Austausch „im Web“, in einem Format, das man theoretisch auch mit einem Texteditor bearbeiten kann – ja, das ist in gewissem Sinne schon was feines. Man kann theoretisch alles schön abstrakt machen, und für spezielle Zwecke spezielle Transformationen angeben, die das Ganze dann in ein weniger abstraktes Format bringen, um zum Beispiel den selben Datensatz sinnvoll in einem Webbrowser, aber eben auch in einem Terminal oder einem Braille-Ausgabegerät, oder gar in Soundausgabe, ausgeben zu können, soweit das geht.

Abstraktion ist sehr wichtig, und eigentlich einer der wenigen Gründe, soetwas wie XML eher zu benutzen, als Flash oder PDF-Dateien. Leider sehen das viele Leute nicht so, und ich sehe immer mehr Internetseiten, die entweder fast nur auf Flash oder – wenn nicht – zumindest sehr stark auf eingebundenen Bildern basieren, ohne die der Webauftritt keinen Sinn mehr ergeben würde. Blinde Menschen sind dabei eine Minderheit, über die man sich scheinbar gerne hinwegsetzt. „Multimedia“ ist wichtiger. Und so sehe ich, wie Menschen („Webdesigner“) gelernt bekommen, Seiten, die scheinbar optisch ansprechend sind, aber XML-Fehler enthalten, und im Grunde für Behinderte Menschen dieser Art überhaupt nicht zugänglich sind, zu produzieren. Klar, Blinde, Taube, und anderweitig behinderte Menschen sind eine Minderheit, und da die „Kommerzialisierung des Web“ ja unbedingt vorangetrieben werden muss, damit auch der letzte Depp seinen Hintern vor den Schreibtisch bewegt, und lernt, seine Playstation zu bedienen, kann man auf solche Minderheiten keine Rücksicht nehmen, und sie müssen sich dem Kommerz unterordnen – sicher gibt es auch irgendwann Webangebote, die sich ausschließlich an diese Personen richten. Jedenfalls beschränkt sich die „Unterstützung“ von Webseiten meistens auf Browser – und oft sogar dort nur auf Spezialfälle (Internet Explorer, Firefox). Insbesondere wenn man zu den modernen „Webinterfaces“ kommt, die auf AJAX basieren.

AJAX – Asynchronous JavaScript and XML – Jene „Technologie“, in der man HTTP-Requests „im Hintergrund“ versenden kann, ohne dass der Nutzer es direkt merkt, mit schönen XML-Datensätzen. Birgt viele neue Gefahren, aber es ist im Grunde sinnvoll, eine solche Möglichkeit zu haben. Anschließend kann man mittels DOM sein Webinterface verändern. Schlecht daran ist, dass das Ganze damit kaum noch barrierefrei ist, da meistens AJAX-Interfaces dazu neigen, „Fenster“, und „schwebende“ Schaltflächen selbst zu implementieren. Schade eigentlich.

Über die konkrete Implementierung kann man sich streiten. Soweit ich das verstanden habe legt man auf eine Schicht zum asynchronen Verschicken von Datenpaketen – IP – eine Schicht, die einen synchronen Stream herstellt – TCP – darauf legt man wiederum eine Schicht zum (ziemlich) asynchronen Verschicken von Datenpaketen, obgleich diese erheblich größer sein können – HTTP – darauf legt man dann wiederum eine Schicht, um mehrere solcher Datenpakete wiederum in einer korrekten Reihenfolge „synchronisieren“ zu können – eine „Technologie“ namens Cookies (ja, genau, das sind diese bösen Dinger, von denen man immer hört…) – um damit im Endeffekt wiederum sowas wie Streams (z.B. in AJAX-Interfaces) realisieren zu können – klar, man nennt es nicht Streams, es sind auch nicht „genau“ Streams, aber es ist mehr oder weniger synchronisierter Datenaustausch.

Macht nix – Hauptsache es geht. Nunja, das hat nun aber relativ wenig mit XML zu tun, hier wird XML ja wenigstens noch als Austauschformat benutzt. Wenigstens kann man hier mit Recht von soetwas wie einem „Standard“ sprechen – es hat sich langsam entwickelt – jemand hat es implementiert, jemand anderes hat es genutzt, dann haben andere etwas ähnliches implementiert, das man auch nutzen konnte, und so hat sich allmählich daraus etwas entwickelt, was mehr oder weniger überall funktioniert, vielleicht nicht immer gleich, aber zumindest ähnlich genug, um mit ein wenig Abstraktion portablen Code zu schreiben. Das Ganze mag kompliziert sein, aber es ist durch einen evolutorischen Process entstanden, und kann sich daher wohl inzwischen mit Recht „Standard“ nennen.

Sehr viele „Standards“ entstehen auf diese Weise – jemand erfindet etwas, viele benutzen es, viele machen es nach, und am Ende versucht man sich auf Gemeinsamkeiten zu einigen, und die viele solcher Standards sind zwar komplizierter als sie sein müssten, aber sie funktionieren und sind weit verbreitet. Meines Wissens sind große Teile von dem, was man aus dem HTML/JavaScript/CSS-Bereich kennt, so entstanden.

Standards können auch dadurch entstehen, dass eine Person etwas entwickelt, und es bereits die meisten Bedürfnisse in einer Weise abdeckt, die Alternativentwicklungen sinnlos macht. Zum Beispiel, weil jemand lange genug an etwas forscht, bevor er es „veröffentlicht“, und z.B. genügend benutzbaren Code produziert und hinreichend kleine Lizenzgebühren dafür verlangt. Soweit ich weiß sind große Teile von HTTP und die Anfänge von XMPP auf diese Weise entstanden, und SGML – der Vorgänger von XML, ich bin mir aber bei dem Ganzen nicht sicher.

Nun, durchdachte Standards sind wohl auch häufig etwas einfacher Gestrickt als deren evolutorisch entstandene Kollegen, denn wenige Entwickler hatten einen Grundgedanken und haben ihn „maßgeschneidert“. Zumindest dachte ich das bisher.

Nun, im Zusammenhang mit XML und dem World Wide Web Consortium drängt sich mir jedoch immer mehr ein anderer Eindruck auf. Zusammenhängende, zusammenpassende, durchdachte Standards sehen für mich jedenfalls anders aus.

Gleich bei XML fällt auf, dass es zwei Argumentationsmethoden gibt: Die ATTLIST und die Sub-Elemente. Es ist also z.B. ein Unterschied, ob man schreibt <tag arg=“value“ /> oder ob man schreibt <tag><arg>value</arg></tag>. Klar, man wollte hier zweifelsohne die Kompatibilität mit HTML wahren, aber ich finde das Ganze einfach wahnsinnig hässlich. Es sollte nur eine Art von Argumenten geben, ist zumindest meine Meinung. Aber das ist ein eher kleiner Kritikpunkt, und es hat wenigstens Historische Gründe.

Dass DTD’s – also Datatype Definitions – neben der Tatsache, dass sie eine eigene Syntax haben, anstatt richtige XML-Syntax, einige künstliche Beschränkungen haben, und eine äußerst komplizierte Methode benötigen, um „include“-Dateien einzufügen, die mir noch immer nicht so ganz klar ist – sei auch mal ignoriert.

Inzwischen gibt es ja neue „Empfehlungen“, ich hörte von RelaxNG (weiß aber nichts davon) und XML Schema. XML Schema Definitionen sind wenigstens richtige XML-Datensätze, und keine Sondersyntax. Nun, was kann ich konkret gegen XML Schema sagen? Eigentlich nichts – „technisch“ gesehen ist es sehr „leistungsfähig“, man kann sehr viel damit ausdrücken und spezifizieren. Aber anstatt hauptsächlich die Schwächen und Inkonsistenzen der alten DTDs zu entfernen, werden neue Schwächen hinzugefügt (auf die ich jetzt nicht näher eingehen will – es gibt einige Teile der „Empfehlung“, die nicht ganz konsequent sind), eine Fülle von Datentypen. Ich verweise mal auf den Wikipedia-Artikel, und erinnere daran, dass es eigentlich darum ging, eine einfache Grammatik zur genaueren Specifikation eines XML-Substandards anzugeben. Wem das Ganze nicht viel zu komplex dafür ist, der hat wohl das Zeug zum ITioten. Man sieht hier eine Tendenz: Durch das hinzufügen von „Features“ versucht man, die Beschränktheit in den Griff zu kriegen.  Es gibt nach Wikipedia also xsd:string xsd:decimal xsd:integer xsd:float xsd:boolean xsd:date xsd:time. Was ist nun aber, wenn ich eine zehnstellige hexadezimalzahl angeben können will? Da bleibt mir nur xsd:string, wobei ich vermute mich erinnern zu können, dass man Strings durch reguläre Ausdrücke beschränken kann – aber selbst wenn: Was ist, wenn ich z.B. nur Primzahlen zulassen will (das kann in der Technik durchaus vorkommen)… „Ist ja egal, das kann ja dann der Interpreter machen. Sowas gehört nicht in den Validator. Der soll ja nur die Grundtypen angeben.“ – Diese oder eine Ähnliche Antwort erwarte ich auf die Frage, zumindest, wenn ich überhaupt eine Antwort bekäme. Warum man gerade diese Datentypen und nicht andere nimmt, nun, das wird wohl aus einem Minimum an Pragmatik und einem Maximum an Tradition entstanden sein. Mein Vorschlag wäre – um den Standard wirklich allgemein zu halten – Strings z.B. durch JavaScript (oder irgendeine andere turingmächtige Sprache, die dazu fähig ist) „validierbar“ zu machen, im Sinne von <xsd:string validator=“function validate (string) { … }“ /> oder etwas Ähnlichem. Ich fasse das Ganze nur als „Spezifikation“ auf – DTDs waren ursprünglich auch nicht „verpflichtend“, man konnte validieren, musste aber nicht – und das Validieren darf meiner Meinung nach ruhig damit einhergehen, ein paar JS-Funktionen auszuführen. Es obliegt dann dem Verfasser einer Datentypendefinition, dafür zu sorgen, dass die Scripte terminieren und effizient sind. Eigentlich könnte man stattdessen ohnehin gleich nur ein JavaScript oder Ähnliches angeben, das die Baumstruktur mittels DOM durchläuft und ein Boolean zurückgibt. Eigentlich finde ich aber, soetwas gehört garnicht dorthin.

Aber nun genug dazu. DOM finde ich persönlich jetzt eigentlich wieder ganz gut gelungen – ich meine, unnötig kompliziert an einigen Stellen, nicht wirklich komfortabel, nicht wirklich übersichtlich, aber doch im Großen und Ganzen ganz gut gelungen.

Ein weiterer Quasistandard ist XPath. Nun, XPath ist weniger schlimm, wenn man mal verstanden hat, dass es zwei konträre Konzepte mischt. Zum „Suchen“ von Stellen in einem XML-Dokument kann man grundsätzlich wohl zwei „Konzepte“ („Vorstellungen“ von dem was man tut) angeben: Zum Einen kann man sich denken, man befindet sich gerade im Wurzelelement (oder an einer anderen Stelle), und „Wandert“ zu dem Element, zu dem man hinwill. Man gibt also eine Wegbeschreibung an. Zum Anderen kann man sich denken, man sucht „von Oben“ nach einem Element mit der Eigenschaft bla. Das eine Mal gibt man also einen Pfad an, das andere Mal eine Eigenschaft. Beide konzepte sind sich scheinbar sehr ähnlich, und können natürlich dasselbe. Aber es sind unterschiedliche Ideen, die man nicht wirklich mischen sollte. Und in XPath wird meiner Meinung nach genau dies getan. Schauen wir uns ein Beispiel von Wikipedia (siehe obigen Link) an:

  • //child::Buch[count(./Seite)<=100][count(./Seite)>=10] liefert alle Knoten vom Typ „Buch“, die mindestens 10 aber höchstens 100 Kindelemente vom Typ „Seite“ haben. [QUELLE: Wikipedia, siehe obiger Link]

Hier wird – wenn ich mich recht entsinne – erst einmal mittels // indiciert, dass man nach einem Knoten sucht, der vom aktuellen Knoten beliebig tief entfernt sein kann. child::Buch drückt aus, dass die Eigenschaft eines Kindknotens eines Knotens mit dem Namen „Buch“ spezifiziert wird. In den eckigen Klammern wird dann jeweils die gewünschte Eigenschaft genannt. Nun, ganz ohne das Angeben von Eigenschaften kommt man wohl nicht aus, nur finde ich, an diesem Beispiel sieht man deutlich, dass beide Konzepte zu sehr gemischt werden. Zur Angabe eines „Pfades“ (erstes Konzept) würde ich mir mehr sowas von der Form

  • /**/Buch/Seite[count(.)<=100][count(.)>=10]/../

wünschen. Zur Angabe einer „Eigenschaft“, nach der man suchen muss, also einer Proposition über die gesuchten Knoten – der Weg, der mir persönlich besser gefiele – würde ich mir etwas wünschen von der form

  • name(x)="Buch"&10<=count{y: childof(y, x)&name(y)="Seite"}<=100

Dem Hardcore-Techniker mag der Unterschied nicht klar sein (aber der trägt auch nicht zur Lösung bei, sondern gehört mit zum Problem) aber ich persönlich finde das Ganze so erheblich schöner, übersichtlicher, leichter erlernbar, leichter implementierbar. Wieder sehe ich allerdings nicht den echten Vorteil zu einem JavaScript oder einem sonstigen Programm, das sich DOM zu Hilfe nimmt. Ich meine, schlussendlich wird wohl jede Software, die XPath-Ausdrücke auswerten kann, irgendetwas in der Art ohnehin verwenden.

Nunja, kommen wir kurz zu SVG: Scalable Vector Graphics. Ein recht schönes Format, das leider meiner Meinung nach keine Zukunft haben wird, zumindest im „Web“ nicht, als Archivierungsformat – naja, vielleicht, wenn man vorher einen guten specialisierten Kompressionsalgorithmus drüberlaufen lässt (also im Endeffekt die Struktur des Formats übernimmt, aber XML und Sonderfallzeugs kekst) weil es bei der Archivierung ein Stück weit ja auch auf den Speicherplatzverbrauch ankommt. Ansonsten weiß ich nur wenig darüber, ich wollte mal kurz eine Library dazu für Common Lisp schreiben, habe damit aber mangels Motivation wieder aufgehört. Nun, was mich daran konkret gestört hat, waren z.B. rotation-Anweisungen als Strings. Es mag ein trivialer Parser sein, den man braucht, um eine Anweisung der Form rotation(1.9 .07 3.2972) zu interpretieren, aber es ist immernoch ein Parser. Und das obwohl XML eine Struktur vorgibt, die man verwenden könnte, anstatt ein eigenes Format zu verwenden. Warum also nicht anstatt transform="rotate(1 2 3)" eine sub- oder supernode der form <transform><rotate center="2 3" angle="1"/></transform> oder Ähnliches? „Listen“ der Form center="2 3" sind im XML-Standard soweit ich weiß definiert als Listen – das heißt, jeder XML-parser kann damit wohl umgehen. Aber Anweisungen mit geklammerten Argumenten – davon weiß ich bisher nichts.

Soetwas finde ich halt schade. Man schafft hier eine Schwäche, weil man die Stärken von XML nicht nutzt. Und die liegen nunmal darin, Bäume anzugeben. Und jeder der schon mal in einem Lisp-Dialekt programmiert hat, und sich über die Struktur von Programmen in High-Level-Sprachen (selbst in C) gedanken gemacht hat, wird bestätigen können: All your code are consist of trees. Jawoll! Jeder Ort hat ein Bühl, auf jedem Bühl wächst ein Baum, auf jedem Baum sitzt ein Bülbül.

Dennoch ist es soweit ich es mitbekommen habe bei SVG ja noch moderat. Zum Beispiel verglichen mit XSLT. XSLT, jene „Programmiersprache“, die den Anspruch erhebt, XML-Syntax zu haben. Mein erster Eindruck von XSLT war eher positiv: Die Grundidee – XML-Syntax benutzen – fand ich gut, aufgrund der eben genannten Ausführungen, denn ich denke, je weniger unnötige Syntax, desto besser (und wem es zu viel Tipparbeit ist, der kann ja einen XML-Editor benutzen, der Tipparbeit spart), und ich merkte schnell, dass einige Konzepte, die ich aus Common Lisp kannte, scheinbar wenigstens schlecht kopiert wurden. Ein Funktionsaufruf mit zwei Argumenten ist zwar vierzeilig, aber wer denkt in dem Zusammenhang schon an Zeilen, das ist doch viel zu Low-Level. Jedenfalls trügte der Eindruck, und bald fragte ich mich, was das Ganze eigentlich soll. Ich persönlich hatte massive Probleme damit, einfachste Dinge (vertauschen von Zeilen und Spalten einer Tabelle, Anordnen von Tabellen) zu implementieren – für Vieles, z.B. die Anordnung von Tabellen – gibt es zwar vordefinierte Funktionen, aber rein theoretisch müsste XSLT Turingmächtig sein, also sollte eine solche Funktion auch selbst implementierbar sein. Mir persönlich war XSLT zu kompliziert, ich sah viel zu wenig Vorteile davon, die Möglichkeiten einer Sprache künstlich zu beschränken, um dann wieder an anderer Stelle zusatzfunktionen zu liefern. Aber ich will darauf jetzt mal garnicht so genau eingehen. Lieber möchte ich das Folgende XSLT-Script zeigen:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:template match="/fac">
                <result>
                        <xsl:call-template name="fact">
                                <xsl:with-param name="fct">1</xsl:with-param>
                                <xsl:with-param name="par" select="normalize-space(text())" />
                        </xsl:call-template>
                </result>
        </xsl:template>
        <xsl:template name="fact">
                <xsl:param name="fct">1</xsl:param>
                <xsl:param name="par" />
                <xsl:if test="$par=0">
                        <xsl:number value="$fct" />
                </xsl:if>
                <xsl:if test="$par&gt;0">
                        <xsl:call-template name="fact">
                                <xsl:with-param name="fct" select="($fct)*($par)" />
                                <xsl:with-param name="par" select="($par)-1" />
                        </xsl:call-template>

</xsl:if>

        </xsl:template>
</xsl:stylesheet>

Ist das nicht wunderschön? Dieses Script ist dazu da, ein XML-Dokument der Form <fac> nummer </fac> in ein XML-Dokument der Form <result> fakultät-der-nummer </result> umzuwandeln. Klappt bei kleinen Zahlen auch ganz gut, bei größeren wird das Ergebnis zu Infinity oder etwas Ähnlichem. Um dieses Script ausführen zu können braucht man einen XML-Parser, einen Parser für URL’s, denn Namespaces müssen valide URL’s sein, einen Auswerter für XQuery-Ausdrücke, und einen Auswerter für die Berechnungen der Form ($fct)*($par), etc., dass das Ganze nicht so ganz „ideal“ ist, zeigt sich zum Beispiel dadurch, dass der Tag <xsl:if test=“$par&gt;0″> kein Tippfehler ist – tatsächlich muss man hier &gt; angeben – das heißt, man braucht sogar noch Escape-Sequenzen (aber gut, die zähle ich mal wohlwollend zum XML-Parser). Ich verstehe hier wiederum nicht, warum man sich dann nicht lieber mehr an Lisp gehalten hat, um etwas zu bekommen, was ungefähr so aussieht:

<stylesheet document="doc">
 <defun name="fact" params="arg1">
  <if>
   <number-equal><value var="arg1"/><integer code="0" /></number-equal>
   <integer code="0" />
   <times>
    <value var="arg1">
    <funcall name="fact"><param name="arg1"><dec><value var="arg1" /></dec></param></funcall>
   </times>
  </if>
 </defun>
 <defun name="main">
  <if><symbol-equal><name><value var="doc" /></name><symbol code="fac" /></symbol-equal>
   <quote> <result> <unquote>
    <funcall name="fact">
     <param name="arg1"><subelement><value var="doc" /></subelement></param>
    </funcall>
   </unquote> </result> </quote>
   <quote> <result> Error </result> </quote>
 </defun>
</stylesheet>

Ich überlasse es mal dem Gewandten Leser, zu versuchen, die Definition zu verstehen, und den „Standard“, den ich mir dahinter überlegt habe. Ein vergleichbarer Code in einer Lisp-Ähnlichen Syntax, der für einen Lisp-Kundigen Menschen wohl verständlich genug ist, sähe wohl so aus:

(stylesheet (doc)
 (defun fact (arg1)
  (if (number-equal arg1 0) 0 (times arg1 (fact (dec arg1))))))
 (defun main ()
  (if (symbol-equal (name doc) 'fac)
    '(result ,(fact (subelement doc)))
    '(result "Error"))))

Hier vermutlich wieder gleiches Problem: Der Techniker sieht nicht den Unterschied. Hier wird mehr oder weniger „Vollständig“ XML-Syntax verwendet – auch zum Addieren, auch zum Variablenzugriff, zu allem. Soetwas ist wünschenswert – zumindest meiner Meinung nach. Ob man es nun genau so implementiert, dass es dann obigen Code ergeben würde, oder ganz anders, ist ja erstmal unwesentlich, hauptsache man nutzt sich die Stärken von XML aus – und bleibt nicht immer nur bei den Schwächen hängen.

Mag sein, dass in meinen Ausführungen eher ein Haufen Ideologie steckt, als ein Haufen technischer Träumereien und Realisierungsphantasien. Für mich ist XML eine Sprache zum Austausch strukturierter Daten im Internet. Weit verbreitet, relativ flexibel, aber inzwischen total überentwickelt. Ich persönlich finde Lisp-Syntax schöner, aber auch das ist eine Frage des Geschmacks. Bei XML handelt es sich genau wie bei Lisp meines Wissens um S-Ausdrücke. Zwischen Lisp-Code und XML gibt es „homomorphismen“, alles was in XML ausdrückbar ist, kann man in ähnlicher Weise in Lisp ausdrücken, umgekehrt geht das auch, allerdings nicht immer so einfach. Ich persönlich fände eine Rückkehr zur strukturellen Betrachtung in den Standards schön, sprich Standards, die über Baumstrukturen definiert sind, und nicht über XML-Dokumente, sodass XML nur einen Unterbau darstellt, und nicht zum Absolutum wird. Die Entwicklung wird aber vermutlich in die andere Richtung gehen. Naja, was solls. Es gibt Schlimmeres.

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: