molily Navigation

DOM 3 Load and Save in Opera 7.6

Eine Einführung in die Benutzung des DOM-Moduls Load and Save mit Opera 7.6

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 (&#8364; für €) oder JavaScript-Escape-Sequenzen (\u20AC für €) zur Verfügung.

Weiterführende Artikel

Letzte Änderung: 07.02.2006