| 
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
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.
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.
|