Der Webbrowser Opera bietet seit der Vorab-Version 7.6 Preview 1 und somit seit der endgültigen Version 8.0 die erste JavaScript- bzw. ECMAScript-Umsetzung des W3C-Standards DOM 3 Load and Save. (Gecko unterstützt einen kleinen, mittlerweise verworfenen Teil eines veralteten Arbeitsentwurfs.)
Das Modul ermöglicht es unter anderem, externe XML-Dokumente oder Strings mit XML-Dokumenten einzulesen, sodass sie als DOM-Document-Objekte zur Verfügung stehen. Über die bekannten DOM-Core-Methoden kann das Dokument im Speicher ausgelesen und manipuliert werden. Anschließend kann es wieder als Markup per HTTP PUT zum Server übertragen werden. So können bequem strukturierte Daten in Form von XML, also auch zum Beispiel XHTML, zwischen Clientbrowser und Webserver ausgetauscht werden.
Solche Aufgaben werden momentan zumeist mit dem nicht-standardisierten XMLHttpRequest
-Objekt gelöst. Dieses wurde ursprünglich von Microsoft für den Internet Explorer entwickelt und wird mittlerweile auch von Gecko, Safari 1.2, Konqueror 3.3 und der genannten Vorab-Version von Opera unterstützt. Im Gegensatz zu DOM Load & Save bietet sich XMLHttpRequest
für die praktische Anwendung an, zum Beispiel basiert der E-Mail-Service Gmail auf dieser Technik. XMLHttpRequest
ermöglicht es zudem, andere Dateiformate als XML einzulesen sowie HEAD- und POST-Anfragen abzusetzen. Aus diesem Grund wird Gecko Load & Save voraussichtlich nicht unterstützen. Denn Load & Save hat längst nicht die Fähigkeiten, die die Techniken XMLHttpRequest, DOMParser und XMLSerializer vermögen, die Gecko momentan unterstützt.
Unterstützung für Load and Save abfragen
Der vorgesehene Weg, um in Erfahrung zu bringen, ob der Browser das Modul unterstützt, führt über DOMImplementation
:
if (document.implementation && document.implementation.hasFeature && document.implementation.hasFeature('LS', '3.0')) { // Browser unterstützt DOM 3 Load and Save } else { // Keine Unterstützung (oder nicht DOM-fähig) }
Parser erzeugen
Die Hauptmethoden von Load and Save hängen am Objekt document.implementation
(DOMImplementationLS
erweitert DOMImplementation
).
Um ein XML-Dokument aus einem String oder einer externen Quelle in ein Document
-Element einzulesen, wird zunächst ein LSParser
-Objekt erzeugt.
var parser = document.implementation.createLSParser( document.implementation.MODE_SYNCHRONOUS, 'http://www.w3.org/TR/REC-xml');
Als Schema-Sprache wird XML DTD angegeben (http://www.w3.org/TR/REC-xml
). Möglich ist auch zum Beispiel XML Schema (http://www.w3.org/2001/XMLSchema
).
Ein XML-Dokument per HTTP einlesen
Über die Methode parseURI
des LSParser
-Objekts kann ein XML-Dokument von einem HTTP-Server über eine GET-Anfrage eingelesen werden. parseURI
parst das Markup und gibt ein DOM-Document
-Objekt zurück.
Da alle Methoden von Load and Save im Fehlerfall sogenannte Exceptions erzeugen (DOMException
, LSException
), muss das try
-catch
-Statement verwendet werden, um den Fehler abzufangen. Der Browser würde die Scriptausführung sonst abbrechen. Falls zum Beispiel ein Fehler beim Parsen des XML-Dokuments auftritt, hat die code
-Eigenschaft des LSException
-Objekts zum Beispiel den Wert 81 (PARSE_ERR
).
try { var doc = parser.parseURI('beispiel.xml'); } catch (e) { window.alert('parser.parseURI: Fehlercode ' + e.code); }
Auf das erzeugte Document
-Objekt kann wie gewohnt über die DOM-Core-Methoden zugegriffen werden. Wenn es sich beispielsweise um ein XHTML-Dokument handelt, kann das title
-Element folgendermaßen ausgelesen oder auch manipuliert werden:
if (doc) { window.alert(doc.getElementsByTagName('title').item(0).firstChild.nodeValue); }
Obwohl im Beispiel ein XHTML-Dokument eingelesen wurde, ist der Zugriff darauf nur über die DOM-Core-Methoden möglich, nicht über die speziellen Methoden des DOM HTML. Der Dokumenttitel lässt sich also nicht über doc.title
auslesen.
In das Dokument können beispielsweise Benutzereingaben eingefügt werden oder dessen Daten werden in das aktuelle (X)HTML-Dokument eingefügt.
Serializer erzeugen
Um das Dokument oder einzelne Knoten (Node
) wieder in Markup zu überführen, wird ein LSSerializer
benötigt:
var serializer = document.implementation.createLSSerializer();
Knoten in einen String überführen
Die Methode writeToString
des LSSerializer
-Objekts gibt das Dokument beziehungsweise einen Knoten in Markup-Form als String zurück.
try { var xmlstring = serializer.writeToString(doc); } catch (e) { window.alert('serializer.writeToString: Fehlercode ' + e.code); } if (xmlstring) window.alert(xmlstring);
Flexibles Serialisieren
Neben dem einfachen writeToString
gibt es die allgemeine Methode write
, welche die Ausgabe in ein LSOutput
-Objekt schreibt, das die Methode als zweiten Parameter entgegennimmt. Dem LSOutput
-Objekt kann vorher über die encoding
-Eigenschaft eine Zeichenkodierung zugewiesen werden. Über die Eigenschaft systemId
kann eine URI angegeben werden, unter der die Ausgabe gespeichert werden soll (siehe auch writeToURI
weiter unten).
var output = document.implementation.createLSOutput(); output.encoding = "UTF-8"; try { var serialize_result = serializer.write(doc, output); } catch (e) { window.alert('serializer.write: Fehlercode ' + e.code); } if (serialize_result) window.alert(output.characterStream);
Der Aufruf von write
erzeugt eine Exception mit dem Wert 9 (DOMException.NOT_SUPPORTED_ERR
). Dieses Verfahren unterstützt Opera also noch nicht.
Serialisiertes Dokument mit HTTP PUT an den Server senden
Die Methode writeToURI
des LSSerializer
-Objekts ermöglicht es, das serialisierte Dokument in eine URI zu schreiben (wie der Aufruf von write
mit einem LSOutput
-Objekt, bei dem systemId
gesetzt ist).
Falls es sich um eine HTTP-URI handelt, sollte der Browser das XML-Dokument mit der PUT-Methode an den Webserver übertragen.
try { var serialize_result = serializer.writeToURI(doc, 'http://example.org/a.xml'); } catch (e) { window.alert('serializer.writeToURI: Fehlercode ' + e.code); } if (serialize_result) window.alert(output);
Der Aufruf von write
erzeugt ebenfalls eine DOMException.NOT_SUPPORTED_ERR
. Das Zurücksenden zum Server funktioniert also nicht. Hierzu müsste das besagte XMLHttpRequest
verwendet werden. Darüber kann Opera 7.6 die XML-Daten zumindest über die POST-Methode übertragen.
String mit XML-Markup in ein Document
-Objekt parsen
Ein String mit einem XML-Dokument kann in ein Document
-Objekt geparst werden. Dazu wird mit createLSInput
ein LSInput
-Objekt erstellt. Dieses Objekt besitzt verschiedene Eigenschaften, darunter stringData
. Darüber wird der String angegeben, der das XML-Dokument enthält. Mit der parse
-Methode des LSParser
-Objekts wird anschließend das LSInput
-Objekt geparst. Diese Methode gibt schließlich das DOM-Document
-Objekt zurück.
var input = document.implementation.createLSInput(); input.stringData = '<?xml version="1.0" encoding="utf-8" ?>\n' + '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' + ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + '<html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">\n' + '<head>\n' + '<title>Testtitel<\/title>\n' + '<\/head>\n' + '<body>\n' + '<p>Testabsatz<\/p>\n' + '<\/body>\n' + '<\/html>'; try { var doc = parser.parse(input); } catch (e) { window.alert('parser.parse: Fehlercode ' + e.code); } if (doc) window.alert(doc.getElementsByTagName('title').item(0).firstChild.nodeValue);
Das Setzen des Attributs encoding
scheint ebenso wie die encoding
-Angabe in der XML-Deklaration keine Auswirkung zu haben. Der String muss daher dieselbe Kodierung verwenden wie das Dokument, in dem er notiert wird. An versteht sich das von selbst. Folgendes wird in einem ISO-8859-1-kodierten Dokument nicht funktionieren:
input.encoding = 'UTF-8'; input.stringData = '<?xml version="1.0" encoding="utf-8" ?>\n" + "<data>Ein UTF-8-kodiertes Euro-Zeichen: €<\/data>';
Die Oktettfolge 0xE2, 0x82, 0xAC wird nicht als UTF-8-kodiertes »€« erkannt. (Das Steuerzeichen 0x82
darf sowieso nicht in einem XML-Dokument vorkommen.) Daher sollte man entweder direkt UTF-8 verwenden. Alternativ stehen numerische Zeichenreferenzen (€
für €) oder JavaScript-Escape-Sequenzen (\u20AC
für €) zur Verfügung.
Weiterführende Artikel
- DOM3 Load and Save example, Cédric Savarese
- Client-side data management with XML (part 3: Opera’s DOM 3 Load & Save), Laurens Holst
Letzte Änderung: 07.02.2006