Werbung einblenden Werbung ausblenden


Home / Tutorials / JavaScript Handbuch / XML Dokumente parsen


XML Dokumente parsen
Ermitteln eines Knotennamens
Laden eines XML Dokumentes mit Netscape
Laden eines XML Dokumentes mit dem Internet Explorer
Die Namen der Knoten rausfischen
Die Namen aller Kindknoten ermitteln
Die Namen aller Kindknoten ermitteln, auch der Kindeskinder
Textknoten eliminieren
Den Inhalt eines Knotens ermitteln
Transformation in ein HTML Dokument ohne die HTML Elemente mit DOM zu generieren
Transformation einer XML Seite in eine HTML Seite. Die HTML tags werden mit dem DOM Ansatz generiert.
Auslesen eines XML Dokumentes durch Aufruf eines XSLT Stylesheets

XML Dokumente parsen

Wem noch nicht klar ist, was XML ist, der kann zum Handbuch über XML hopsen. XML Handbuch. Wir haben nichts anderes erwartet. Auch hier beschreiten der Explorer und Netscape unterschiedliche Wege. XML Dokumenten lassen sich nur mit Netscape aber Version 6 und dem Explorer ab Version 5 parsen. Wir gehen von folgender XML Datei aus, die allen Beispielen zugrunde liegt. Diese Datei liegt in einem Ordner beispiele (sic!), der sich auf derselben Hierarchiestufe liegen muss, wie das JavaScript.

Ermitteln eines Knotennamens

<?xml version="1.0" encoding="ISO-8859-1"?>
<buecher>
<Sachbuecher>
<Autor Nationalität="Deutsch">Prof.Dr. Wirrwärr</Autor>
<Titel>Kafka und Felice Bauer</Titel>
<Erscheinungsjahr>1987</Erscheinungsjahr>
<status>verkauft</status>
</Sachbuecher>
<Romane>
<Autor Nationalität="Schweiz">Hans Donnerknall</Autor>
<Titel>Ewig ruft der Berg</Titel>
<Erscheinungsjahr>1956</Erscheinungsjahr>
</Romane>
</buecher>

Bevor wir den Skript zeigen, mit dem einen Knotennamen ermitteln kann, machen wir uns erstmal klar, von was die Rede ist indem wir hier clicken.

Wir sehen also, dass wir Sachbuecher erhalten, wenn wir den Netscape verwenden und Romane, wenn wir den Explorer verwenden. By the way, für Leute die sich jetzt wundern,
wir haben das Ergebnis in einen div Bereich geschossen. Das ist aber immer Moment ziemlich egal. Wir erhalten also den ersten (Exploder) bzw. den zweiten (Netscpae) Kindknoten
des Wurzelknotens buecher. Der Skript, der das veranstaltet, sieht so aus.

<script language=javascript>
function dererste()
{
banane="";

if (document.implementation.createDocument)
{
xml_dokument = document.implementation.createDocument("", "", null);
xml_dokument.onload = hole_die_Knoten2;
}
else if(window.ActiveXObject)
{
xml_dokument = new ActiveXObject("Microsoft.XMLDOM");

xml_dokument.onreadystatechange = function ()
{if (xml_dokument.readyState == 4) hole_die_Knoten2()};

}
else
{
alert('Browser ist weder Netscape 6.0 noch Explorer 5.0 folglich funzt es nicht');
return;
}
xml_dokument.load("beispiele/buecher.xml");
}

function hole_die_Knoten2()
{
var array_mit_allen_Elementen = xml_dokument.getElementsByTagName('buecher');
document.getElementById('rindamit').innerHTML="<font color=blue size=5>"+array_mit_allen_Elementen[0].childNodes[1].nodeName+"</font>";
}

</script>

<A href=javascript:dererste()>hier</A>

Laden eines XML Dokumentes mit Netscape

Wir sehen also, dass die Vorgehensweise je nach Browser unterschiedlich ist. Es muss also eine Möglichkeit geben, herauszufinden, mit welchen Browser man es im Moment zu tun hat. Handelt es sich um den Netscape Browser, dann existiert das Objekt document.implementation. Dieses hat die Methode createDocument, mit der man eine Instanz eines XML Dokumentes generieren kann. Die Funktion hat zwei drei Parameter, den Namespace und das Wurzelelement. Das kann man brauchen, wenn man nicht ein fertiges XML laden will, sondern selber eines generieren will. Was der dritte Parameter bedeutet, ist mir unklar. An diese Instanz des XML Dokument Objektes kann man den event handler onload binden. Das bewirkt dann, dass die Funktion hole_die_Knoten aufgerufen wird, wenn das die Instanz des XML Dokument Objektes geladen wurde.

Laden eines XML Dokumentes mit dem Internet Explorer

Mit dem Explorer funktionniert das Laden eines XML Dokumentes völlig anders. Zuerst überprüfen wir, ob das Objekt window.ActiveXObject vorhanden ist. Ist das der Fall, haben wir den Internet Explorer Version 5 oder höher vor uns. Mit xml_dokument=new ActiveXObject("Microsoft.XMLDOM"); bilden wir eine Instanz eines XML Dokumentes. (By the way: Mehr zur Terminologie der objektorientierten Programmierung findet sich im Perl und im PHP Handbuch,perl, PHP. Aber, um der Wahrheit die Ehre zu geben, es ist hier eigentlich völlig egal, ob man das mit dem objektorientierten Ansatz versteht oder nicht.) Leider lässt sich beim Explorer an eine Instanz eines XML Dokumentes kein event handler binden. Mit onreadystatechange lässt sich aber der Zustand des Objektes ermitteln. Nachdem die Methode ausgeführt wurde, hat readyState einen der folgenden Werte.

0 wenn das Objekt noch nicht initialisiert wurde
1 das zu ladende Objekt lädt Daten
2 das geladene Objekt hat die Daten geladen
3 mit den geladenen Daten kann gearbeitet werden
4 Das Objekt ist vollkommen initialisiert


Uns interessiert aber in diesem Zusammenhang nur, ob das Objekt vollkommen initialisiert wurde. Ist dies der Fall, rufen wir die Funktion hol_die_Knoten auf.

Die Namen der Knoten rausfischen

Die Art und Weise, wie man auf ein XML Dokument zugreift, wenn man es geschafft hat eines zu kreiieren und in dieses XML Dokument Werte hineingeladen hat, ist dann bei beiden Browsern zwar nicht gleich, aber immerhin ähnlich, das ist ja schon mal was, wir verlangen ja nicht mehr viel. Mit var array_mit_allen_Elementen = xml_dokument.getElementsByTagName('buecher'); packen wir den Wurzelknoten, wobei wir aber auch jeden anderen Knoten hätten greifen können. Wir haben also einen Array, mit einem Element, da wir ja nur einen Wurzelknoten haben. Mit array_mit_allen_Elementen[0].childNodes[1].nodeName; Packen wir von diesem Wurzelknoten den ersten Kindknoten und von diesem wiederum den Namen. Warum kriegen wir jetzt aber bei Netscape Sachbuecher und beim Explorer Romane ? Netscape sieht direkt Unterhalb des angesprochenen Knotens einen Textknoten. Folglich ist Netscape hat Netscape einen Knoten mehr als der Explorer. Wir werden, nachdem wir uns noch ein bisschen damit beschäftigt haben, die Knoten anzusteuern, ein work around für dieses Problem vorstellen.

Die Namen aller Kindknoten ermitteln

Bevor wir den Skript, der alle Kindknoten des Wurzelknotens rausfischt, schauen wir uns erstmal an, von was die Rede ist, indem wir hier clicken.

Allora, tutto chiaro ? Wir erhalten, in Abhängigkeit vom Browser folgende Ergebnisse.

bei Netscape: #text
  Sachbuecher
  #text
  Romane
  #text
 
beim Explorer: Sachbuecher
  Romane

Der Skript, der uns dieses Ergebnis auf den Schirm setzt, sieht so aus.

<script language=javascript>
function xml_dokument_importieren2()
{
banane="";

if (document.implementation.createDocument)
{
xml_dokument = document.implementation.createDocument("", "", null);
xml_dokument.onload = hole_die_Knoten4;
}
else if(window.ActiveXObject)
{
xml_dokument = new ActiveXObject("Microsoft.XMLDOM");

xml_dokument.onreadystatechange = function ()
{if (xml_dokument.readyState == 4) hole_die_Knoten4()};

}
else
{
alert('Browser ist weder Netscape 6.0 noch Explorer 5.0 folglich funzt es nicht');
return;
}
xml_dokument.load("beispiele/buecher.xml");
}

var banane="";

function hole_die_Knoten4()
{
var array_mit_allen_Elementen = xml_dokument.getElementsByTagName('buecher');

for(i=0;i<array_mit_allen_Elementen[0].childNodes.length;i++)
{
banane=banane+" <font color=blue size=5> "+array_mit_allen_Elementen[0].childNodes[i].nodeName+"</font><br>";
document.getElementById('rindamit2').innerHTML=banane;
}
}
</script>

Den oberen Teil kennen wir schon, neu ist für uns nur das.

for(i=0;i<array_mit_allen_Elementen[0].childNodes.length;i++)
{
banane=banane+" <font color=blue size=5> "+array_mit_allen_Elementen[0].childNodes[i].nodeName+"</font><br>";
document.getElementById('rindamit2').innerHTML=banane;
}

array_mit_allen_Elementen ist der Array, den wir mit getElementsByTagName('buecher') gebildet haben. Da wir nur ein Element buecher haben, schliesslich ist es das Wurzelelement, hat unser Array auch nur ein Element. Von diesem, unserem einzigen Knoten, wollen wir wissen, wieviele Kindknoten er hat, denn wir wollen ja die Namen aller Kindknoten ermitteln. Das machen wir mit childNodes.length. Wir lassen also die for Schleife durch alle Kindknoten wandern und ermitteln mit childNodes[i].nodeName den Namen. Wir erhalten nur die Kindknoten direkt unter buecher aber nicht die Kindeskinderknoten. Dass wir beim Explorer und bei Netscape andere Ergebnisse erhalten liegt daran, dass für Netscape ein Textknoten auch ein Kindknoten ist, und zwar unabhängig davon, ob überhaupt einer da ist. Wir werden später sehen, wie wir die aus dieser unterschiedlichen Interpretation resultierenden Probleme lösen.

Die Namen aller Kindknoten ermitteln, auch der Kindeskinder

Bevor wir den Skript, der uns die Namen aller Knoten, also auch der Kindeskinderknoten auf den Schirm setzt, schauen wir erstmal, von was die Rede ist.

Bevor wir den Skript, der alle Kindknoten des Wurzelknotens rausfischt, schauen wir uns erstmal an, von was die Rede ist, indem wir hier clicken.

Lo habéis entendido ? Alles klar ? Wir kriegen in rot die Kindknoten und in blau die Kindeskindknoten. Auch hier haben wir wieder das gleiche Phänomen. Netscape liefert uns auch die Textknoten. Der Skript, der das bewerkstelligt hat, sieht so aus.

<script language=javascript>
function xml_dokument_importieren3()
{
banane="";

if (document.implementation.createDocument)
{
xml_dokument = document.implementation.createDocument("", "", null);
xml_dokument.onload = hole_die_Knoten6;
}
else if(window.ActiveXObject)
{
xml_dokument = new ActiveXObject("Microsoft.XMLDOM");

xml_dokument.onreadystatechange = function ()
{if (xml_dokument.readyState == 4) hole_die_Knoten6()};

}
else
{
alert('Browser ist weder Netscape 6.0 noch Explorer 5.0 folglich funzt es nicht');
return;
}
xml_dokument.load("beispiele/buecher.xml");
}

var banane="";

function hole_die_Knoten6()
{
var array_mit_allen_Elementen = xml_dokument.getElementsByTagName('buecher');

for(i=0;i<array_mit_allen_Elementen[0].childNodes.length;i++)
{
banane=banane+" <font color=red size=5> "+array_mit_allen_Elementen[0].childNodes[i].nodeName+"</font><br>";

for(j=0;j<array_mit_allen_Elementen[0].childNodes[i].childNodes.length;j++)
{
banane=banane+" <font color=blue size=5> "+array_mit_allen_Elementen[0].childNodes[i].childNodes[j].nodeName+"</font><br>";
}
}
document.getElementById('rindamit3').innerHTML=banane;
}
</script>

Die Logik dahinter ist einigermassen simpel. Wir ermitteln zu jedem Kindknoten die Anzahl seiner Kindknoten (childNodes[i].childNodes.length) und lassen ermitteln dann in einer zweiten for Schleife den Namen dieser Kindeskindknoten.

Textknoten eliminieren

Wie bereits erwähnt, erhalten wir bei Netscape mit dem Attribut nodeName auch die Textknoten, was eigentlich merkwürdig ist, da ein Textknoten ja von der Natur der Sache her keinen Namen hat. Will man diese Textknoten nicht haben, so kann man sie mit dem Attribut nodeType eliminieren. Auch nodeType ist im Detail beim Explorer und bei Netscape unterschiedlich implementiert, die Übereinstimmung reicht aber so weit, dass wir unser Problem lösen können.
nodeType ->1 --> es handelt sich um einen Element Knoten
nodeType->3 --> es handelt sich um einen Textknoten
Wenn wir ermitteln können, und genau das können wir, um welchen Typ von Knoten es sich handelt, dann können wir die Knoten, die keine Element Knoten sind in einer if Bedingung abfangen.

<script language=javascript>
function xml_dokument_importieren4()
{
banane="";
if (document.implementation.createDocument)
{
xml_dokument = document.implementation.createDocument("", "", null);
xml_dokument.onload = hole_die_Knoten7;
}
else if(window.ActiveXObject)
{
xml_dokument = new ActiveXObject("Microsoft.XMLDOM");

xml_dokument.onreadystatechange = function ()
{if (xml_dokument.readyState == 4) hole_die_Knoten7()};

}
else
{
alert('Browser ist weder Netscape 6.0 noch Explorer 5.0 folglich funzt es nicht');
return;
}
xml_dokument.load("beispiele/buecher.xml");
}

var banane="";

function hole_die_Knoten7()
{
var array_mit_allen_Elementen = xml_dokument.getElementsByTagName('buecher');

for(i=0;i<array_mit_allen_Elementen[0].childNodes.length;i++)
{
if(array_mit_allen_Elementen[0].childNodes[i].nodeType !=3)
{
banane=banane+" <font color=red size=5> "+array_mit_allen_Elementen[0].childNodes[i].nodeName+"</font><br>";
}
for(j=0;j<array_mit_allen_Elementen[0].childNodes[i].childNodes.length;j++)
{
if(array_mit_allen_Elementen[0].childNodes[i].childNodes[j].nodeType !=3)
{
banane=banane+" <font color=blue size=5> "+array_mit_allen_Elementen[0].childNodes[i].childNodes[j].nodeName+"</font><br>";
}
}
}
document.getElementById('rindamit4').innerHTML=banane;
}
</script>

Für Leute, die Netscape benutzen, mag es jetzt interessant sein, hier zu clicken. Beim Explorer ergibt sich kein Unterschied.


Den Inhalt eines Knotens ermitteln

In der Regel ist es wesentlich spannender, den Inhalt eines Knotens rauszufischen, als den Namen. Unter Inhalt eines Knotens verstehen wir das, was in einem Knoten drin steht. Wenn das unser Knoten ist.

<Autor Nationalität="Deutsch">Prof.Dr. Wirrwärr</Autor>

Dann ist Prof.Dr.Wirrwär der Inhalt.

Die Vorgehensweise ist verblüffend einfach. Wieder machen wir uns durch eine Click auf hier klar, von was eigentlich die Rede ist.

Der Skript dazu sieht so aus

<script language=javascript>
function xml_dokument_importieren66()
{

if (document.implementation.createDocument)
{
xml_dokument = document.implementation.createDocument("", "", null);
xml_dokument.onload = hole_die_Knoten99;
}
else if(window.ActiveXObject)
{
xml_dokument = new ActiveXObject("Microsoft.XMLDOM");

xml_dokument.onreadystatechange = function ()
{if (xml_dokument.readyState == 4) hole_die_Knoten99()};

}
else
{
alert('Browser ist weder Netscape 6.0 noch Explorer 5.0 folglich funzt es nicht');
return;
}
xml_dokument.load("beispiele/buecher.xml");
}

var banane="";

function hole_die_Knoten99()
{
var array_mit_allen_Elementen = xml_dokument.getElementsByTagName('buecher');

for(i=0;i<array_mit_allen_Elementen[0].childNodes.length;i++)
{
if(array_mit_allen_Elementen[0].childNodes[i].nodeType !=3)
{
banane=banane+" <font color=red size=5> "+array_mit_allen_Elementen[0].childNodes[i].nodeName+"</font><br>";
}
for(j=0;j<array_mit_allen_Elementen[0].childNodes[i].childNodes.length;j++)
{
if(array_mit_allen_Elementen[0].childNodes[i].childNodes[j].nodeType !=3)
{
banane=banane+" <font color=blue size=5> "+array_mit_allen_Elementen[0].childNodes[i].childNodes[j].firstChild.nodeValue+"</font><br>";
}
}
}
document.getElementById('rindamit122').innerHTML=banane;
}
</script>

Alles klar ? Der Skript ist so geschrieben, dass er bei Netscape und dem Internet Explorer das gleiche Ergebnis erzielt. Verändert wurde im Prinzip nur eine Zeile.
array_mit_allen_Elementen[0].childNodes[i].childNodes[j].firstChild.nodeValue
Mit array_mit_allen_Elementen[0].childNodes[i].childNodes[j] marschieren wir durch bis zu den Kindeskindknoten (buecher->Sachbuecher->Autor etc.). Von diesen Kindeskindknoten brauchen wir den ersten Knoten, den das ist der Textknoten. Wir schreiben also firstChild. Von diesem Textknoten wiederum wollen wir den Wert haben. Wir schreiben also nodeValue. Bleibt ein Problem. Wie kriegen wir eigentlich die Attribute und deren Werte ?
Den Namen und den Wert von Attributen ermitteln
Mit Attributen lässt sich ein Knoten genauer bestimmen. Das Element

<Autor Nationalität="Deutsch">Prof.Dr. Wirrwärr</Autor>

hat zum Beispiel ein Attribut, nämlich Nationalität und dieses hat den Wert "Deutsch".

Man kann sich jetzt erstmal anschauen von was die Rede ist, indem man hier clickt.

Der Skript, der das bewerkstelligt, sieht so aus.

<script language=javascript>
function attribute_zeigen()
{
banane="";

if (document.implementation.createDocument)
{
xml_dokument = document.implementation.createDocument("", "", null);
xml_dokument.onload = hole_die_Knoten188;
}
else if(window.ActiveXObject)
{
xml_dokument = new ActiveXObject("Microsoft.XMLDOM");

xml_dokument.onreadystatechange = function ()
{if (xml_dokument.readyState == 4) hole_die_Knoten188()};

}
else
{
alert('Browser ist weder Netscape 6.0 noch Explorer 5.0 folglich funzt es nicht');
return;
}
xml_dokument.load("beispiele/buecher.xml");
}

var banane="";

function hole_die_Knoten188()
{
banane="";
var array_mit_allen_Elementen = xml_dokument.getElementsByTagName('buecher');
banane=banane+" <font color=blue size=5> "+array_mit_allen_Elementen[0].childNodes[0].childNodes[0].attributes[0].nodeName+"</font>";
banane=banane+" <font color=blue size=5> "+array_mit_allen_Elementen[0].childNodes[0].childNodes[0].attributes[0].nodeValue+"</font><br>";
banane=banane+" <font color=blue size=5> "+array_mit_allen_Elementen[0].childNodes[0].childNodes[0].attributes[0].nodeType+"</font><br>";
document.getElementById('rindamit177').innerHTML=banane;
}
</script>

Alles klar ? Wir erhalten vom ersten Knoten den ersten Knoten (den Kindeskindknoten in Bezug auf das Wurzelelement, von diesem wiederum holen wir uns alle Attribute als Array, wobei wir in diesem Falle nur eines haben und dieses eine fischen wir uns dann mit attributes[0] raus. Von diesem lassen wir und dann den Wert und den Namen zeigen. Das funktionniert natürlich nur mit dem Explorer, weil wir es noch nicht für beide Browser programmiert haben und folglich Netscape, wie oben dargestellt, auf den falschen Knoten zugreift. (Genau genommen zeigt er einen Fehler an, weil der erste Knoten, der Textknoten, kein Attribut hat). Schliesslich lassen wir uns noch den Knotentyp anzeigen. Attributsknoten haben den Wert 2 (Funktionniert erst ab Explorer Version 6 und Netscape Version 6).
Crossbrowser kompatible Programmierung eines Programmes, dass sowohl den Namen des Elementes, den Inhalt des Elementes, den Namen des Attributes, wie auch den Inhalt des Attributes anzeigt.

Zuerst schauen wir uns an, was wir erreichen wollen, indem wir hier clicken.

Der Skript, der das auf den Schirm setzt, sieht dann so aus.

<script language=javascript>
function tutti_insieme22()
{

if (document.implementation.createDocument)
{
xml_dokument = document.implementation.createDocument("", "", null);
xml_dokument.onload = hole_die_Knoten1994;
}
else if(window.ActiveXObject)
{
xml_dokument = new ActiveXObject("Microsoft.XMLDOM");

xml_dokument.onreadystatechange = function ()
{if (xml_dokument.readyState == 4) hole_die_Knoten1994()};

}
else
{
alert('Browser ist weder Netscape 6.0 noch Explorer 5.0 folglich funzt es nicht');
return;
}
xml_dokument.load("beispiele/buecher.xml");
}

var banane="";

function hole_die_Knoten1994()
{
var array_mit_allen_Elementen = xml_dokument.getElementsByTagName('buecher');

for(i=0;i<array_mit_allen_Elementen[0].childNodes.length;i++)
{
if(array_mit_allen_Elementen[0].childNodes[i].nodeType !=3)
{
banane=banane+" <font color=red size=5> "+array_mit_allen_Elementen[0].childNodes[i].nodeName+"</font><br>";
}
for(j=0;j<array_mit_allen_Elementen[0].childNodes[i].childNodes.length;j++)
{
if(array_mit_allen_Elementen[0].childNodes[i].childNodes[j].nodeType !=3)
{
banane=banane+" <font color=blue size=5> "+array_mit_allen_Elementen[0].childNodes[i].childNodes[j].firstChild.nodeValue+"</font><br>";
if(array_mit_allen_Elementen[0].childNodes[i].childNodes[j].getAttribute("Nationalität") !=null && array_mit_allen_Elementen[0].childNodes[i].childNodes[j].getAttribute("Nationalität") !="")
{
banane=banane+" <font color=green size=5>Nationalität "+array_mit_allen_Elementen[0].childNodes[i].childNodes[j].getAttribute("Nationalität")+"</font><br>";
}
}
}
}
document.getElementById('rindamit664').innerHTML=banane;
}
</script>

Wir sehen also, dass sich das Auslesen der Attribute relativ einfach gestaltet. Wir benötigen hierfür ledinglich die Funktion getAttribute. Diese Funktion liefert beim Explorer null wenn das Element kein Attribut hat, und den Wert des Attributes, wenn es ein solches hat. Bei Netscape liefert nichts wenn das Element kein Attribut hat und den Wert des Attributes, wenn ein solches vorhanden ist. Da die Rückgabewerte für den Explorer und für Netscape also unterschiedlich sind, müssen wir die if Bedingung entsprechend formulieren, so dass nur die Elemente auf das Vorhandensein von Attributen untersicht werden, die tatsächlich auch ein Attribut haben. Es gehört nicht besonders viel Phantasie dazu, sich vorzustellen, dass das parsen eines XML Dokumentes mit dem document model object (dom) Ansatz sehr schnell, sehr kompliziert werden kann, insbesondere dann, wenn das XML Dokument nicht ausbalanciert ist. Von ausbalancierten XML Dokumenten spricht man dann, wenn jeder Zweig des Baumes die gleiche Tiefe hat. Bis jetzt haben wir die Dokumente lediglich ausgelesen, aber wir haben sie noch nicht, bzw. nur ansatzweise, in ein HTML Dokument konvertiert. Wir können das entweder so machen wie bisher, indem wir einfach HTML schreiben, denn dies haben wir bislang ansatzweise getan, oder indem wir mit dem DOM Ansatz ein HTML Dokument produzieren. Die dritte Möglichkeit wäre, die XML Datei mit XSLT zu transformieren, ein Ansatz, den wir dann weiter unten vorstellen.

Transformation in ein HTML Dokument ohne die HTML Elemente mit DOM zu generieren

Dieser Ansatz ist wohl der einfachste. Wir betten die ermittelten Knotenwerte einfach in HTML ein und sind fertig. Um das Ergebnis zu sehen, muss man hier clicken.

Allora mi faccio capire ?? Der Skript ist an sich selbsterklärend.

<script language=javascript>
function tuttiinsieme33X()
{
banane="";
if (document.implementation.createDocument)
{
xml_dokument = document.implementation.createDocument("", "", null);
xml_dokument.onload = hole_die_Knoten1994XX;
}
else if(window.ActiveXObject)
{
xml_dokument = new ActiveXObject("Microsoft.XMLDOM");

xml_dokument.onreadystatechange = function ()
{if (xml_dokument.readyState == 4) hole_die_Knoten1994XX()};

}
else
{
alert('Browser ist weder Netscape 6.0 noch Explorer 5.0 folglich funzt es nicht');
return;
}
xml_dokument.load("beispiele/buecher.xml");
}

var banane="";
Beschriftung=new Array("Autor","Titel","Erscheinungsjahr","Status");

function hole_die_Knoten1994XX()
{
var array_mit_allen_Elementen = xml_dokument.getElementsByTagName('buecher');

for(i=0;i<array_mit_allen_Elementen[0].childNodes.length;i++)
{
banane=banane+"<table border=1 width=300>";
if(array_mit_allen_Elementen[0].childNodes[i].nodeType !=3)
{
banane=banane+"<tr><td>Kategorie</td><td> "+array_mit_allen_Elementen[0].childNodes[i].nodeName+"</td></tr>";
}
for(j=0;j<array_mit_allen_Elementen[0].childNodes[i].childNodes.length;j++)
{
if(array_mit_allen_Elementen[0].childNodes[i].childNodes[j].nodeType !=3)
{
banane=banane+"<tr><td>"+Beschriftung[j]+"</td>
<td>"+array_mit_allen_Elementen[0].childNodes[i].childNodes[j].firstChild.nodeValue+"</td></tr>";
if(array_mit_allen_Elementen[0].childNodes[i].childNodes[j].getAttribute("Nationalität") !=null && array_mit_allen_Elementen[0].childNodes[i].childNodes[j].getAttribute("Nationalität") !="")
{
banane=banane+" <tr><td>Nationalität </td><td> "+array_mit_allen_Elementen[0].childNodes[i].childNodes[j].getAttribute("Nationalität")+"</td></tr>";
}
}
}
banane=banane+"</table><br>";
}
document.getElementById('rindamit667X').innerHTML=banane;
}
</script>

Er produziert HTML, in diesem Konkreten Fall sind die Werte der Knoten in einen Table eingebettet. Dieser Ansatz wird selten beschrieben, obwohl es der einfachste ist. Mit dem DOM Ansatz die HTML Seite zu produzieren ist eigentlich komplizierter.

Transformation einer XML Seite in eine HTML Seite. Die HTML tags werden mit dem DOM Ansatz generiert.

Bevor wir den Skript durchsprechen, schauen wir erstmal was passiert, indem wir hier clicken.

Der Skript, der uns das auf den Schirm setzt,sieht so aus.

<script language=javascript>
function tutti_insieme_dom()
{

if (document.implementation.createDocument)
{
xml_dokument = document.implementation.createDocument("", "", null);
xml_dokument.onload = hole_die_Knoten_dom;
}
else if(window.ActiveXObject)
{
xml_dokument = new ActiveXObject("Microsoft.XMLDOM");

xml_dokument.onreadystatechange = function ()
{if (xml_dokument.readyState == 4) hole_die_Knoten_dom()};

}
else
{
alert('Browser ist weder Netscape 6.0 noch Explorer 5.0 folglich funzt es nicht');
return;
}
xml_dokument.load("beispiele/buecher.xml");
}


var banane="";
Beschriftung=new Array("Autor","Titel","Erscheinungsjahr","Status");


function hole_die_Knoten_dom()
{
Beschriftung=new Array("Autor","Titel","Erscheinungsjahr","Status");


var array_mit_allen_Elementen = xml_dokument.getElementsByTagName('buecher');

for(i=0;i<array_mit_allen_Elementen[0].childNodes.length;i++)
{


var neuer_table = document.createElement('TABLE');
neuer_table.setAttribute('width',300);
neuer_table.setAttribute('border',1);
var neuer_body = document.createElement('TBODY');
neuer_table.appendChild(neuer_body);

if(array_mit_allen_Elementen[0].childNodes[i].nodeType !=3)
{
var neue_zeile = document.createElement('TR');
neuer_body.appendChild(neue_zeile);
neue_zelle=document.createElement('TD');
neue_zeile.appendChild(neue_zelle);
inhalt=document.createTextNode("Kategorie");
neue_zelle.appendChild(inhalt);
neue_zelle=document.createElement('TD');
neue_zeile.appendChild(neue_zelle);
inhalt=document.createTextNode(array_mit_allen_Elementen[0].childNodes[i].nodeName);
neue_zelle.appendChild(inhalt);

}

for(j=0;j<array_mit_allen_Elementen[0].childNodes[i].childNodes.length;j++)
{

if(array_mit_allen_Elementen[0].childNodes[i].childNodes[j].nodeType !=3)
{
var neue_zeile = document.createElement('tr');
neuer_body.appendChild(neue_zeile);
var neue_zelle=document.createElement('td');
neue_zeile.appendChild(neue_zelle);
inhalt=document.createTextNode(Beschriftung[j]);
neue_zelle.appendChild(inhalt);

var neue_zelle=document.createElement('td');
neue_zeile.appendChild(neue_zelle);
inhalt=document.createTextNode
(array_mit_allen_Elementen[0].childNodes[i].childNodes[j].firstChild.nodeValue);
neue_zelle.appendChild(inhalt);

if(array_mit_allen_Elementen[0].childNodes[i].childNodes[j].getAttribute("Nationalität") !=null && array_mit_allen_Elementen[0].childNodes[i].childNodes[j].getAttribute("Nationalität") !="")
{

var neue_zeile = document.createElement('tr');
neuer_body.appendChild(neue_zeile);

var neue_zelle=document.createElement('td');
neue_zeile.appendChild(neue_zelle);
inhalt=document.createTextNode("Nationalität");
neue_zelle.appendChild(inhalt);

var neue_zelle=document.createElement('td');
neue_zeile.appendChild(neue_zelle);
inhalt=document.createTextNode
(array_mit_allen_Elementen[0].childNodes[i].childNodes[j].getAttribute("Nationalität"));
neue_zelle.appendChild(inhalt);
}
}
}
document.getElementById('rindamit_dom').appendChild(neuer_table);
}
}
</script>

Wie unschwer zu erkennen, ist das komplizierter, als die Transformation mit dem oben beschriebenen Ansatz. Das prinzipielle Verfahren sieht so aus. XML Dokumente, und HTML ist lediglich ein Spezialfall eines solchen, sieht ineinander verschachtelt (zumindest im Idealfall). Folglich muss man diese hierarchische Struktur abbilden. Das heisst, man hat immer ein Element, dass alle Elemente umfasst, in dieses wiederum ist ein Element eingebettet, dass wiederum andere Elemente umfassen kann, in dieses wiederum ist ein Element ........
In unserem Beispiel haben wir das Element table, in dieses wiederum ist das Element tr eingebettet und in das Element tr wiederum das Element td. In dem Element td steckt dann der eigentlich Inhalt. Wir kreieren also zu Beginn jeder Schleife ein table Element.
var neuer_table = document.createElement('TABLE');
und weisen diesem Attribute zu
neuer_table.setAttribute('width',300);
neuer_table.setAttribute('border',1);
Anschliessend durchlaufen wir in der ersten for Schleife die Elemente auf der obersten Ebene, also Sachbuercher und Romane. Der Charme von XML besteht nun übrigens darin, soit dit en passant, dass wir beliebieg viele Elemente hinzufügen können, ohne den Skript deshalb verändern zu müssen. Innerhalb dieser for Schleife bilden wir dann einen Zeile in die wir zwei Zellen einbinden.
var neue_zeile = document.createElement('TR');
neuer_body.appendChild(neue_zeile);
neue_zelle=document.createElement('TD');
neue_zeile.appendChild(neue_zelle);
inhalt=document.createTextNode("Kategorie");
neue_zelle.appendChild(inhalt);
neue_zelle=document.createElement('TD');
neue_zeile.appendChild(neue_zelle);
inhalt=document.createTextNode(array_mit_allen_Elementen[0].childNodes[i].nodeName);
neue_zelle.appendChild(inhalt);
Man beachte, dass wir den Textknoten nicht wie einen "normalen" Knoten einhängen können. Einen Textknoten müssen wir mit createTextNode bilden und nicht mit createElement. In der nächsten for Schleife durchlaufen wir alle Kindknoten von Sachbücher bzw. Romane und machen dort wieder genau das gleiche. Schluss endlich hängen wir die fertige virtuelle XML Datei in unseren div.
document.getElementById('rindamit_dom').appendChild(neuer_table);
Wundern kann man sich noch über das Element TBODY
var neuer_body = document.createElement('TBODY');
neuer_table.appendChild(neuer_body);
dass wir, nachdem wir es kreiert haben in unseren table einhängen. Wir brauchen dieses Element zwar nicht, aber der Explorer will das aus irgendwelchen unerfindlichen Gründen haben, sonst funktionniert es nicht.

Auslesen eines XML Dokumentes durch Aufruf eines XSLT Stylesheets

Der Explorer ab Version 6 und Netscape ab Version 7 unterstützen das clientseitige Auslesen einer XML Datei über ein XSLT Stylesheet. Eine ausführliche Beschreibung von XSLT findet sich im XML Handbuch unter
XML Handbuch. Wenn wir einen mit dem obigen Beispiel identische HTML Seite über XSLT generieren wollen, sähe das dazugehörige XSLT Stylesheet so aus.

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html><head><title>Hübsche Tabelle mit XSLT</title></head><body>
<xsl:apply-templates select="buecher/Sachbuecher | buecher/Romane"/>
</body></html>
</xsl:template>
<xsl:template match="Sachbuecher | Romane">
<table border="1" width="300">
<tr><td>Kategorie</td><td><xsl:value-of select="name()"/></td></tr>
<xsl:for-each select="child::*">
<tr><td><xsl:value-of select="name()"/></td><td><xsl:value-of select="."/></td></tr>
</xsl:for-each>

</table><br/>
</xsl:template>

</xsl:stylesheet>


Die XML Datei ist zu modifizieren. Es muss eine processing instruction hinzugefügt werden, damit überhaupt klar ist, mit welchem XSLT Stylesheet die XML Datei abgearbeitet werden soll. Die modifizierte XML Datei sieht dann so aus.

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>

<buecher>
<Sachbuecher>
<Autor Nationalität="Deutsch">Prof.Dr. Wirrwärr</Autor>
<Titel>Kafka und Felice Bauer</Titel>
<Erscheinungsjahr>1987</Erscheinungsjahr>
<status>verkauft</status>
</Sachbuecher>
<Romane>
<Autor Nationalität="Schweiz">Hans Donnerknall</Autor>
<Titel>Ewig ruft der Berg</Titel>
<Erscheinungsjahr>1956</Erscheinungsjahr>
</Romane>
</buecher>

Beide Dateien sind in irgendeinen Ordner zu werfen, die XML Datei tauft man am besten text.xml und die XSL Datei tauft man am besten test.xsl. Anschliesend ruft man die XML Datei auf mit Laufwerk:\Name_des_Ordners\test.xml (oder halt mit Datei->Datei öffnen etc.).

Wir sehen dann sowas auf dem Schirm.

vorhergehendes Kapitel