Suchen im Katalog Zu Bücher A-Z
Java Kochbuch

Java Kochbuch


Ian F. Darwin
1. Auflage Januar 2002
ISBN 3-89721-283-8
908 Seiten

Kapitel 21

XML

21.0 Einführung

Die Extensible Markup Language, kurz XML, ist ein portierbares, für Menschen lesbares Format zum Austausch von Texten oder Daten zwischen Programmen. XML leitet sich von dem Mutter-Standard SGML ab, genau wie die Sprache HTML, die weltweit auf Webseiten benutzt wird. XML ist somit das jüngere, aber leistungsfähigere Geschwisterchen von HTML. Da die meisten Entwickler wenigstens ein klein wenig HTML kennen, werden Teile der folgenden Diskussion sich zum Vergleich auf HTML beziehen. Die weniger bekannte Großmutter von XML ist GML, die General Markup Language von IBM, und eine ihrer Cousinen ist das Maker Interchange Format (MIF) des Adobe FrameMaker. Abbildung 21-1 gibt die Ahnentafel wieder.

Abbildung 21-1: Die Ahnen von XML

Man kann sich XML wie HTML vorstellen, aber bereinigt, konsolidiert und mit der Möglichkeit, eigene Tags zu definieren. Es ist HTML mit Tags, die den Informationsgehalt identifizieren können und sollen, nicht aber die Formatierung. Eine andere Betrachtungsweise für XML sieht diese Sprache als allgemeines Austauschformat für Business-to-Business-Kommunikation im Internet oder als von Menschen edierbare1 Beschreibung von so unterschiedlichen Dingen wie Textverarbeitungsdateien und Java-Dokumenten. XML ist all das, je nachdem, welchen Hintergrund Sie als Entwickler haben und wo Sie heute - und morgen - noch hin wollen.

Wegen der breiten Akzeptanz für XML wird dieses Format als Grundlage für viele andere Formate benutzt, unter anderem für das Dateisicherungsformat von Open Office (http://www.openoffice.org), für das Grafikdateiformat SVG und viele andere.

Von SGML haben sowohl HTML als auch XML die Syntax der spitzen Klammern (< und >) geerbt, die die Tags umgeben, von denen jeweils ein Paar einen Teil eines XML-Dokuments umschließt, der Element genannt wird. Ein Element kann Inhalt umfassen (wie etwa das Tag <P> in HTML) oder auch nicht (wie das <HR> in HTML). Während HTML-Dokumente entweder mit einem <HTML>- oder mit einem <DOCTYPE...>-Tag beginnen können (in informeller Schreibweise sogar ohne beide), muß eine XML-Datei immer mit einem XML-Prolog beginnen, der zumindest wie folgt aussieht:

 <?xml version="1.0"?>

Das Fragezeichen ist ein Sonderzeichen, das dazu dient, den XML-Prolog zu identifizieren. (Es ist syntaktisch vergleichbar mit dem %, das in ASP und JSP verwendet wird).

HTML hat eine Reihe von Elementen, die Attribute tragen können, beispielsweise:

 <BODY BGCOLOR=white> ... </body>

In XML müssen Attributwerte (wie die 1.0 als Versionsangabe im Prolog oder das Wort white in BGCOLOR) in Anführungszeichen stehen. Mit anderen Worten: Anführungszeichen sind in HTML optional, in XML hingegen erforderlich.

Ein weiterer Unterschied zwischen HTML und XML besteht darin, daß XML zwischen Groß- und Kleinschreibung unterscheidet, so daß BODY, Body und body drei verschiedene Elementnamen sind. Das oben gezeigte Beispiel mit BODY ist zwar in HTML erlaubt, würde aber jeden XML-Parser zu Klagen veranlassen. Da wir gerade über das Parsen von XML sprechen: Es ist eine große Vielfalt von XML-Parsern erhältlich. Ein Parser ist einfach ein Programm (oder eine Klasse), das eine XML-Datei liest, sie zumindest syntaktisch analysiert und Ihnen den Zugriff auf einzelne oder alle darin enthaltenen Elemente gestattet. Die meisten dieser Parser verhalten sich wie die Java-Bindungen für eine der beiden wohlbekannten XML-APIs, nämlich SAX und DOM. SAX, die Simple API for XML, liest die Datei und ruft Ihren Code auf, wenn sie auf gewisse Ereignisse trifft, beispielsweise Elementstart oder -ende und ähnliches. DOM, das Document Object Model, liest die Datei und konstruiert im Speicher einen Baum oder Graph, der den Elementen und ihren Attributen sowie Inhalten in der Datei entspricht. Dieser Baum kann durchlaufen, geändert (mit DOM sogar aus dem Nichts heraus aufgebaut) oder in eine Datei geschrieben werden.

Eine alternative API namens JDOM ist ebenfalls als Open Source veröffentlicht worden. JDOM, geschaffen von Brett McLaughlin und Jason Hunter, hat den Vorteil, hauptsächlich auf Java ausgerichtet zu sein (DOM wurde so entworfen, daß es mit vielen verschiedenen Sprachen zurecht kommt). JDOM ist unter http://www.jdom.org erhältlich; es wurde als JSR (Java Standards Request) für den Sun Community Standards Process akzeptiert.

Aber woher weiß der Parser, ob eine XML-Datei die richtigen Elemente enthält? Nun, die einfacheren, »nicht-validierenden« Parser wissen das nicht; sie prüfen nur, daß der XML-Code syntaktisch korrekt oder wohlgeformt ist. Validierende Parser prüfen, ob die XML-Datei sich an eine vorgegebene Document Type Definition (DTD) oder ein XML-Schema hält. DTDs sind ein Erbstück von SGML; ihre Syntax wird in Rezept 21.4 besprochen. Schemas sind neuer als DTDs. Zwar sind sie komplizierter, sie bieten dafür aber solche objektbasierten Möglichkeiten wie Vererbung. DTDs werden in einer speziellen Metasprache geschrieben, die aus SGML abgeleitet ist, während XML-Schemas in »reinem« XML geschrieben werden.

Sie können XML aber nicht nur parsen, sondern auch mit einem XML-Prozessor in ein anderes Format wie beispielsweise HTML transformieren. Das ist wie geschaffen für die Verwendung in Servlets (siehe Kapitel 18): Wenn ein bestimmter Web-Browser XML unterstützt, geben Sie die Dateien unmittelbar aus, wenn aber nicht, dann wandeln Sie sie in HTML um. Es gibt zwei Transformationssprachen: XSL-T und XSL-FO, die wir uns zuerst ansehen werden. Für komplexere Operationen auf XML-Dateien gibt es zwei Parsing-APIs, die wir später besprechen werden.

Wenn Sie Kontrolle darüber brauchen, wie ein XML-Dokument angezeigt wird, können Sie XSL-FO (Extensible Style Language: Formatting Objects) verwenden. XSL-FO ist eine erweiterte Fassung des Stylesheet-Begriffs von HTML, mit dessen Hilfe Sie Formatierungen für bestimmte Elemente festlegen können. Allerdings ist der Standard XSL-FO noch nicht vollständig. Außerdem kann XML-FO kompliziert sein; im wesentlichen geben Sie eine Batch-Formatierungssprache an, die beschreibt, wie Ihre Textdaten auf der Druckseite formatiert werden. Eine umfassende Referenzimplementierung liegt mit FOP vor. Dieses Programm erzeugt Ausgaben in Acrobat PDF und ist bei http://xml.apache.org erhältlich.

21.1 XML mit XSLT transformieren

Problem

Sie müssen wesentliche Änderungen des Ausgabeformats vornehmen.

Lösung

Benutzen Sie XSLT; es ist ziemlich leicht anzuwenden und benötigt nicht viel Java-Code.

Diskussion

XSLT, die Extensible Stylesheet Language for Transformations, erlaubt Ihnen viel Kontrolle über das Ausgabeformat. Mit XSLT kann man eine XML-Dtei von einer DTD in eine andere umwandeln; das ist z. B. nützlich, um im Rahmen einer Business-to-Business-Anwendung (B2B) Informationen, die nach einer bestimmten Industrie-Standard-DTD formatiert sind, an eine andere Stelle weiterzuleiten, die eine andere DTD verwendet. Man kann damit aber auch andere Ausgabeformate wie beispielsweise HTML erzeugen. Stellen Sie sich XSLT als Skriptsprache zur Umformung von XML vor.

Sie benötigen dazu einige Klassen, die zusammen einen XSLT-Prozessor ausmachen. Ein kostenlos erhältlicher XSLT-Prozessor ist Xalan aus dem Apache-Projekt (anfangs von Lotus/IBM als Lotus-XSL-Prozessor angeboten). Um Xalan zu verwenden, erzeugen Sie ein XSL-Prozessor-Objekt, indem Sie die Fabrikmethode getProcessor() aufrufen, und rufen dann seine Parser-Methode auf, der Sie zwei XSLTInputSources (eine für das XML-Dokument und eine für das XSL-Stylesheet) und ein XSLTResultTarget als Ausgabedatei übergeben.

Nehmen wir an, Sie haben eine Datei mit den Namen, Adressen usw. von Leuten in einem XML-Dokument wie der in Beispiel 21-1 gezeigten Datei people.xml gespeichert.

Beispiel 21-1: people.xml 
 <?xml version="1.0"?>
 <people>
 <person>
     <name>Ian Darwin</name>
     <email>ian@darwinsys.com</email>
     <country>Kanada</country>
 </person>
 <person>
     <name>Noch ein Darwin</name>
     <email type="intranet">cd@beagle.ac.uk</email>
     <country>England</country>
 </person>
 </people>

Sie können die Datei people.xml mit dem folgenden Befehl in HTML umwandeln:

 $ java XSLTransform people.xml people.xsl people.html

Abbildung 21-2 zeigt, wie die resultierende HTML-Datei in einem Browser aussieht.

Abbildung 21-2: Endergebnis der Umwandlung von XML in HTML

Sehen wir uns die Datei people.xsl an, die in Beispiel 21-2 zu sehen ist. Da eine XSL-Datei immer auch eine XML-Datei ist, muß sie wohlgeformt im Sinne der XML-Syntax sein. Wie Sie sehen, enthält sie einige XML-Elemente, besteht aber überwiegend aus (wohlgeformtem) HTML.

Beispiel 21-2: people.xsl 
 <?xml version="1.0"?>
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:template match="/">
 
 <html>
 <head><title>Unsere Leute</title></head>
 <body>
 
     <table border="1">
     <tr>
         <th>Name</th>
         <th>E-Mail</th>
     </tr>
 
     <xsl:for-each select="people/person">
         <tr>
             <td><xsl:value-of select="name"/></td>
             <td><xsl:value-of select="email"/></td>
         </tr>
     </xsl:for-each>
 
     </table>
 
 </body></html>
 </xsl:template>
 </xsl:stylesheet>

Das Programm XSLTransform erscheint in Beispiel 21-3.

Beispiel 21-3: XSLTransform.java 
 import org.apache.xalan.xslt.*;
 import java.net.*;
 import java.io.*;
 
 /**
  *  Demonstriere Dateitransformation unter Verwendung von XSLT.
  */
 public class XSLTransform {
 
     public static void main(String[] args) {
 
         try {
             // Benötigt drei Eingabeparameter
             if (args.length != 3) {
                 System.out.println("Aufruf: java XSLTransform "
                     + "<XML-Eingabedatei> <XSL-Eingabedatei> <Ausgabedatei>");
                 System.exit(1);
             }
 
             XSLTProcessor myProcessor = XSLTProcessorFactory.getProcessor();
             XSLTInputSource xmlSource = new XSLTInputSource(args[0]);
             XSLTInputSource xslStylesheet = new XSLTInputSource(args[1]);
             XSLTResultTarget xmlOutput = new XSLTResultTarget(args[2]);
             myProcessor.process(xmlSource, xslStylesheet, xmlOutput);
         }
         catch (org.xml.sax.SAXException exc) {
             System.err.println("Ungültiges XML während der Verarbeitung gefunden:");
             exc.printStackTrace();
         }
     }
 }

Siehe auch

In der Entwicklung befinden sich derzeit Translets. Sun entwickelt ein Programm, das ein Stylesheet einliest und daraus eine Translet-Klasse erzeugt, die ein kompiliertes Java-Programm ist, das XML nach den Regeln des Stylesheets transformiert. Dies erspart den Aufwand, das Stylesheet bei jeder Übersetzung eines Dokuments neu einzulesen. Siehe http://www.sun.com/xml/developers/xsltc/.

21.2 XML mit SAX parsen

Problem

Sie wollen einmal schnell über eine XML-Datei laufen und dabei bestimmte Tags oder andere Informationen extrahieren.

Lösung

Benutzen Sie einfach SAX, um einen Dokumenten-Handler zu erzeugen, und übergeben Sie es dem SAX-Parser.

Diskussion

Das Interface DocumentHandler für XML spezifiziert eine Reihe von »Callback«-Methoden, die Ihr Programm zur Verfügung stellen muß. In gewissem Sinne ähnelt dies den Listener-Interfaces in AWT und Swing, die in Rezept 13.4 kurz besprochen wurden. Die gebräuchlichsten Methoden sind startElement(), endElement() und character(). Offensichtlich werden die ersten beiden bei Start und Ende eines Elements aufgerufen, während character() bei Zeichendaten aufgerufen wird. Die Zeichen sind in einem großen Array gespeichert, und Sie erhalten die Array-Basis, den Offset und die Länge der Zeichenfolge als Parameter übergeben, die Ihren Text ausmachen. Praktischerweise gibt es einen String-Konstruktor, der genau diese drei Parameter erwartet. Hmmm, ob sie wohl daran gedacht haben...?

Um dies zu demonstrieren, habe ich ein kleines Programm geschrieben, das unter Verwendung von SAX Namen und E-Mail-Adressen aus einer XML-Datei extrahiert. Das Programm selbst ist ziemlich einfach, wie in Beispiel 21-4 zu sehen ist.

Beispiel 21-4: SaxLister.java 
 import java.io.*;
 import org.xml.sax.*;
 import org.xml.sax.helpers.*;
 import org.apache.xerces.parsers.SAXParser;
 
 /** Einfacher Lister - extrahiere die Tags name und email aus einer Benutzerdatei.
  * Aktualisiert für SAX 2.0
  */
 public class SaxLister {
 
     class PeopleHandler extends DefaultHandler {
 
         boolean name = false;
         boolean mail = false;
 
         public void startElement(String nsURI, String strippedName,
             String tagName, Attributes attributes)
         throws SAXException {
             if (tagName.equalsIgnoreCase("name"))
                 name = true;
             if (tagName.equalsIgnoreCase("email"))
                 mail = true;
         }
 
         public void characters(char[] ch, int start, int length) {
             if (name) {
                 System.out.println("Name:   " + new String(ch, start, length));
                 name = false;
             } else if (mail) {
                 System.out.println("E-Mail: " + new String(ch, start, length));
                 mail = false;
             }
         }
     }
 
     public void list() throws Exception {
         XMLReader parser = XMLReaderFactory.createXMLReader(
             "org.apache.xerces.parsers.SAXParser");    // sollte Properties laden
         parser.setContentHandler(new PeopleHandler());
         parser.parse("people.xml");
     }
 
     public static void main(String[] args) throws Exception {
         new SaxLister().list();
     }
 }

Beim Aufruf ergibt sich die folgende Ausgabe:

 $ java SaxLister
 Name:   Ian Darwin
 E-Mail: ian@darwinsys.com
 Name:   Noch ein Darwin
 E-Mail: cd@beagle.co.uk
 $ 

Ein Problem mit SAX ist, daß es simpel ist. Deswegen ist es nicht gut skalierbar, wie man bei etwas Nachdenken über das Programm leicht einsieht. Stellen Sie sich vor, Sie versuchten, zwölf verschiedene Tags zu verarbeiten, und zwar jedes unterschiedlich. Für gründlichere Analysen einer XML-Datei kann das Document Object Model (DOM) besser geeignet sein. (Andererseits erfordert DOM, daß der gesamte Baum im Speicher gehalten wird; daher gibt es hier Skalierungsprobleme bei extrem großen XML-Dokumenten.) Mit SAX können Sie außerdem nicht wirklich durch ein Dokument »navigieren«, denn Sie erhalten nur einen Ereignis-Stream, nicht aber eine echte Struktur. Dafür benötigen Sie DOM oder JDOM.

21.3 XML mit DOM parsen

Problem

Sie wollen eine XML-Datei im einzelnen untersuchen.

Lösung

Verwenden Sie DOM, um das Dokument zu parsen, und verarbeiten Sie den im Hauptspeicher erzeugten Baum.

Diskussion

Das Document Object Model (DOM) ist eine baumartige Darstellung der Informationen in einem XML-Dokument. Es besteht aus mehreren Interfaces, von denen das wichtigste der Knoten (Node) ist. Alle befinden sich im Package org.w3c.dom, was den Einfluß des World Wide Web-Konsortiums (http://www.w3.org) bei der Erschaffung und Verbreitung des DOM widerspiegelt. Die einzelnen DOM-Interfaces sind in Tabelle 21-1 aufgeführt.

Tabelle 21-1: DOM-Interfaces 
Interface
Funktion
Document
Darstellung eines XML-Dokuments auf höchster Ebene
Node
Darstellung eines beliebigen Knotens im XML-Baum
Element
Ein XML-Element
Text
Text (String)

Sie müssen diese Interfaces nicht implementieren, denn der Parser erzeugt sie. Wenn Sie zum Erzeugen und Ändern von XML-Dokumenten in Rezept 21.5 fortgeschritten sind, können Sie selbst Knoten erzeugen. Selbst dann gibt es jedoch Implementierungsklassen. Ein XML-Dokument mit DOM zu parsen, ist syntaktisch der Dateiverarbeitung mit XSL vergleichbar, das heißt, Sie erhalten eine Referenz auf den Parser und rufen seine Methoden mit Objekten auf, die die Eingabedateien darstellen. Der Unterschied besteht darin, daß der Parser ein XML-DOM zurückgibt, einen Objektbaum im Hauptspeicher. Beispiel 21-5 ist ein Programm, das einfach ein XML-Dokument parst.

Beispiel 21-5: XParse.java 
 import java.io.*;
 import org.w3c.dom.*;
 import com.sun.xml.tree.*;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
 
 /** Parse eine XML-Datei unter Verwendung von DOM. */
 public class XParse {
 
     /** Parse die Datei */
     public static void parse(String fileName) {
         try {
             System.err.println("Parse " + fileName + "...");
 
             // Mache das Dokument zu einer URL, damit relative DTD funktioniert.
             String uri = "file:" + new File(fileName).getAbsolutePath();
 
             XmlDocument doc = XmlDocument.createXmlDocument(uri);
             System.out.println("Parsed OK");
 
         } catch (SAXParseException ex) {
             System.err.println("+================================+");
             System.err.println("|         *Parse-Fehler*         |");
             System.err.println("+================================+");
             System.err.println("+ Line " + ex.getLineNumber ()
                                 + ", uri " + ex.getSystemId ());
             System.err.println(ex.getClass());
             System.err.println(ex.getMessage());
             System.err.println("+================================+");
         } catch(SAXException ex) {
             System.err.println("+================================+");
             System.err.println("|         *SAX-XML-Fehler*       |");
             System.err.println("+================================+");
             System.err.println(ex.toString());
         } catch (IOException ex) {
             System.err.println("+================================+");
             System.err.println("|     *Input/Output-Fehler*      |");
             System.err.println("+================================+");
             System.err.println(ex.toString());
         }
     }
 
     public static void main(String[] av) {
         if (av.length == 0) {
             System.err.println("Aufruf: XParse Datei");
             return;
         }
         for (int i=0; i<av.length; i++) {
             parse(av[i]);
         }
     }
 }

Durchlaufen Sie dann das Dokument. Sie können das vordefinierte TreeWalker-Interface verwenden, Sie können aber auch einfach den in Beispiel 21-6 gezeigten Algorithmus verwenden.

Beispiel 21-6: XTW.java (teilweises Listing) 
 /** Verarbeite alle Knoten rekursiv. */
 protected void doRecursive(Node p) {
    if (p == null) {
          return;
    }
    NodeList nodes = p.getChildNodes();
    int numElem = nodes.getLength();
    Debug.println("xml-tree", "Element hat " + numElem + " Kinder");
    for (int i=0; i<numElem; i++) {
         Node n = nodes.item(i);
         if (n == null) {
             continue;
         }
 
         doNode(n); // Im Online-Quelltext-Archiv enthalten!
 
     }
 }

Ein vollständiges Programmbeispiel, das diesen Lösungsansatz verwendet, finden Sie in Rezept 21.6.

21.4 Die Struktur mit einer DTD verifizieren

Problem

Bisher habe ich einfach XML-Code bereitgestellt und behauptet, daß es sich um gültiges XML handelt. Nun wollen Sie die Struktur mit Hilfe einer Document Type Definition (DTD) verifizieren.

Lösung

Schreiben Sie die DTD, und verweisen Sie in einem oder mehreren XML-Dokumenten darauf.

Diskussion

Hier ist nicht die Stelle für eine vollständige Erörterung über das Schreiben von DTDs. Kurz gesagt besteht eine DTD aus einem Header und einer Aufzählung der Elemente und aller Attribute. Die DTD ist in einer Spezialsprache geschrieben, die Ihnen die Angabe von Elementen und Attributen ermöglicht. Beispiel 21-7 zeigt people.dtd, eine DTD für die oben in diesem Kapitel verwendete Datei people.xml.

Beispiel 21-7: people.dtd 
 <!ELEMENT people (person)*>
 <!ELEMENT person (name, email, country)>
 
 <!ELEMENT name (#PCDATA)>
 <!ATTLIST email type CDATA #IMPLIED>
 <!ELEMENT email (#PCDATA)>
 <!ELEMENT country (#PCDATA)>

Um zu überprüfen, ob eine Datei mit einer DTD übereinstimmt, führen Sie zwei Schritte aus:

1. Verweisen Sie innerhalb der XML-Datei auf die DTD, wie man es manchmal auch in HTML-Dateien sieht. Die Zeile <!DOCTYPE> sollte der Zeile <?xml> folgen, aber vor allen tatsächlichen Daten stehen.
 <?xml version="1.0"?>
 <!DOCTYPE people SYSTEM "people.dtd">
 
 <people>
 <person>
         <name>Ian Darwin</name>
         <email>ian@darwinsys.com</email>
         <country>Canada</country>
 </person>
2. Übergeben Sie der Methode createXMLDocument() als zweiten Parameter den Wert true; das steht für »Erzwinge die Gültigkeit des Dokuments«.
 XmlDocument doc = XmlDocument.createXmlDocument(uri);

Alle in dem Dokument gefundenen Elemente, die der DTD zufolge nicht gültig sind, führen dann zu einer Exception.

21.5 Mit DOM selber XML erzeugen

Problem

Sie wollen Ihre eigenen XML-Dateien erzeugen oder bereits bestehende Dokumente verändern.

Lösung

Verwenden Sie DOM oder JDOM; parsen oder erzeugen Sie das Dokument und rufen Sie dann seine Schreibmethode auf.

Diskussion

Die Klasse XmlDocument von Sun besitzt eine Methode write(), die entweder mit einem OutputStream oder mit einem Writer aufgerufen werden kann. Um sie zu verwenden, erzeugen Sie ein XML-Dokumentenobjekt mit Hilfe des Konstruktors von XmlDocument. Erzeugen Sie die Knoten und klinken Sie sie in den Baum ein. Rufen Sie dann die Methode write() des Dokuments auf. Nehmen wir beispielsweise an, Sie wollten in XML ein Gedicht erzeugen. Wenn Sie das Programm starten und den XML-Code auf die Standard-Ausgabe schicken, könnte das etwa so aussehen:

 $ jikes +E -d . DocWrite.java
 $ java DocWrite
 <?xml version="1.0" encoding="UTF-8"?>
 
 <Poem>
   <Stanza>
     <Line>Zwei Trichter wandeln durch die Nacht.</Line>
     <Line>Durch ihres Rumpfs verengten Schacht</Line>
   </Stanza>
 </Poem>
 $

Das Programm hierfür ist ziemlich kurz, wie man in Beispiel 21-8 sieht.

Beispiel 21-8: DocWrite.java 
 import java.io.*;
 import org.w3c.dom.*;
 import com.sun.xml.tree.*;
 
 /** Erzeuge und schreibe ein XML-Dokument */
 public class DocWrite {
 
     public static void main(String[] av) throws IOException {
         DocWrite dw = new DocWrite();
         XmlDocument doc = dw.makeDoc();
         doc.write(System.out);
     }
 
     /** Ereuge das XML-Dokument */
     protected XmlDocument makeDoc() {
         try {
             XmlDocument doc = new XmlDocument();
 
             Node root = doc.createElement("Poem");
             doc.appendChild(root);
 
             Node stanza = doc.createElement("Stanza");
             root.appendChild(stanza);
 
             Node line = doc.createElement("Line");
             stanza.appendChild(line);
             line.appendChild(
                 doc.createTextNode("Zwei Trichter wandeln durch die Nacht."));
             line = doc.createElement("Line");
             stanza.appendChild(line);
             line.appendChild(;
                 doc.createTextNode("Durch ihres Rumpfs verengten Schacht"));
 
             return doc;
 
         } catch (Exception ex) {
             System.err.println("+============================+");
             System.err.println("|        XML-Fehler          |");
             System.err.println("+============================+");
             System.err.println(ex.getClass());
             System.err.println(ex.getMessage());
             System.err.println("+============================+");
             return null;
         }
     }
 }

Ein vollständigeres Programm würde selbstverständlich eine Ausgabedatei erzeugen und Fehler ausführlicher behandeln. Es würde außerdem mehr Gedichtzeilen enthalten, als ich behalten habe.

Die Klasse XmlDocument von Sun ist kein erklärter Teil des Standards, und daher importiert das Programm com.sun.xml.tree.*. Die APIs anderer Hersteller bieten jedoch sicherlich ähnliche Möglichkeiten. In Version 2 der XML-DOM-API können Sie die neue Methode XMLReaderFactory.createXMLReader() verwenden, die den Namen des Parsers als String-Parameter entgegennimmt, der seinerseits aus einer Properties-Datei (siehe Rezept 7.7) geladen werden kann. Damit vermeidet man es, den Namen der Parser-Klasse in die Anwendung fest hineinzukompilieren.

21.6 Programm: xml2mif

Der Adobe FrameMaker2 benutzt ein Austauschformat namens MIF (Maker Interchange Format), das vage mit XML verwandt ist, das jedoch keine wohlgeformten XML-Dokumente liefert. Wir werden uns jetzt ein Programm ansehen, das mit Hilfe von DOM ein ganzes Dokument einliest und für jeden Knoten MIF-Code erzeugt. Mit diesem Programm wurden einige der ersten Kapitel des Buches erzeugt, das Sie gerade lesen.

Das Hauptprogramm, das in Beispiel 21-9 gezeigt wird, heißt XmlForm; es parst den XML-Code und ruft eine von mehreren Klassen auf, die die Ausgabe erzeugen. Auf dieser Grundlage könnten auch Ausgaben in anderen Formaten erzeugt werden.

Beispiel 21-9: XmlForm.java 
 import java.io.*;
 import org.w3c.dom.*;
 import com.sun.xml.tree.*;
 
 /** Wandle eine einfache XML-Datei in Text um. */
 public class XmlForm {
     protected Reader is;
     protected String fileName;
 
     protected static PrintStream msg = System.out;
 
     /** Konstruierte einen einfachen Konverter bei gegebenem Eingabedateinamen */
     public XmlForm(String fn) {
         fileName = fn;
     }
 
     /** Konvertiere die Datei */
     public void convert(boolean verbose) {
         try {
             if (verbose)
                 System.err.println(">>>Parse " + fileName + "...");
             // Mache eine URL aus dem Dokument, damit relative DTDs funktionieren.
             String uri = "file:" + new File(fileName).getAbsolutePath();
             XmlDocument doc = XmlDocument.createXmlDocument(uri);
             if (verbose)
                 System.err.println(">>>Durchlaufe " + fileName + "...");
             XmlFormWalker c = new GenMIF(doc, msg);
             c.convertAll();
 
         } catch (Exception ex) {
             System.err.println("+================================+");
             System.err.println("|         *Parse-Fehler*         |");
             System.err.println("+================================+");
             System.err.println(ex.getClass());
             System.err.println(ex.getMessage());
             System.err.println("+================================+");
         }
         if (verbose)
             System.err.println(">>>Fertig mit " + fileName + "...");
     }
 
     public static void main(String[] av) {
         if (av.length == 0) {
             System.err.println("Aufruf: XmlForm datei");
             return;
         }
         for (int i=0; i<av.length; i++) {
             String name = av[i];
             new XmlForm(name).convert(true);
         }
         msg.close();
     }
 }

Die eigentliche MIF-Erzeugung ist hier nicht dargestellt, da das eigentlich nichts mit XML zu tun hat; in den Online-Sourcen zum Buch ist dieser Teil jedoch enthalten.

Siehe auch

XML ist ein Gebiet, das sich rasch wandelt. Schemas werden jetzt zur »Realität«. Es erscheinen immer neue APIs (und neue Abkürzungen!). XML-RPC und SOAP ermöglichen es Ihnen, verteilte Anwendungen zu bauen, wobei XML und HTTP dem Programmaustausch dienen. Das W3C läßt viele neue XML-Standards erscheinen. Mehrere Websites verfolgen die Änderungen in der XML-Landschaft nach, darunter auch die offizielle Site des W3C (http://www.w3.org/xml/ ) und die XML-Site von O'Reilly (http:// www.xml.com).

Die Java API for XML Parsing (JAXP) von Sun, das ab Version 1.4 zum Java 2 SDK gehört, stellt Routinen zur Verfügung, die den Zugriff auf eine Vielfalt von Parsern erleichtern. Damit gehören erstmals auch SAX, DOM und XSLT zum Standard-Umfang der Java-APIs.

Viele Bücher wetteifern um die Behandlung von XML. Das reicht von dem einfachen XML: A Primer von Simon St. Laurent (Hungry Minds) bis zur umfassenden XML-Bibel des hochproduktiven Elliotte Rusty Harold (mitp). Dazwischen liegt die Einführung in XML von Erik T. Ray (O'Reilly). Das bei O'Reilly verlegte Java und XML von Brett McLaughlin behandelt diese Themen in größerer Tiefe und deckt auch ab, wie man mit XML Veröffentlichungen erzeugen kann, beispielsweise durch Verwendung von Cocoon aus dem Apache-Projekt, oder wie man XML-Informationskanäle mit Hilfe von RSS unterstützt.

1
Auch wenn Sie XML mit vi, Emacs, notepad oder simpletext edieren können, wird es allgemein als besser angesehen, einen XML-fähigen Editor zu verwenden. Die Struktur von XML ist komplexer, und Parser-Programme sind weit weniger tolerant gegenüber winzigen Fehlern, als es in der HTML-Welt je der Fall gewesen ist. XML-Dateien werden als einfacher Text gespeichert, damit sie sich leichter debuggen lassen, leichter auch zwischen komplett inkompatiblen Betriebssystemen übertragen werden können und damit sie (als letzte Hilfe in der Not) von Hand geändert werden können, um Software-Katastrophen zu reparieren.

2
Früher ein Produkt von Frame Technologies, einer Firma, die von Adobe übernommen wurde.


O'Reilly Home | O'Reilly-Partnerbuchhandlungen | Bestellinformationen
Kontaktieren Sie uns | Über O'Reilly | Datenschutz

© 2001, O'Reilly Verlag GmbH & Co. KG