Die Verarbeitung von XML Dateien hat in den letzten Jahren enorm an Bedeutung gewonnen. Nicht zuletzt durch das immer verstärkte Angebot von WebServices wird die die Markup Language immer wichtiger bei der Verarbeitung von Daten. Daher ist es auch als Java-Softwareentwickler von Vorteil zu wissen, wie XML Dateien bearbeitet werden können.
Für die Verarbeitung von XML Dateien gibt es inzwischen verschiedene Vorgehensweisen. Zunächst ist unter drei verschiedenen Verarbeitungstypen zu unterscheiden:
- DOM-orientierte APIs (liest das komplette XML File ein)
- Push-API (Callback Prinzip – z.B. SAX)
- Pull-API (z.B. StaX)
In diesem Tutorial wird gezeigt, wie ein XML Dokument anhand des XML DOM’s verarbeitet werden können. Hierzu wird mit der Java Schnittstelle JAXP (Java API for XML) gearbeitet. Wird JAXP verwendet, sind keine zusätzlichen API’s notwendig, da JAXP ein Teil der Java API ist.
Ich möchte jeden Leser darauf aufmerksam machen, das in dem Artikel XML – Extensible Markup Language die Metasprache XML näher erläutert wird. Des Weiteren werden in dem Artikel XML Zusatztechnologien die XML Technologien wie beispielsweise XPath, XPointer oder XLink anhand von Beispielen näher beschrieben.
Alternativ kann zu der nachfolgenden XML-Verarbeitung auch das JAXB-Tutorial hilfreich sein.
Vorbereitung
- Neues Projekt erstellen: de.michel.data.xml
- Paket erstellen: dataStorage
- Paket erstellen: model
- Paket erstellen: xml
- dataStorage/XMLinObject.java erstellen
- dataStorage/XMLLiterature.java.java erstellen
- model/Author.java erstellen
- model/Book.java erstellen
- model/Literature.java erstellen
- xml/literature.dtd erstellen
- xml/literature.xml erstellen
literature.xml
In der Datei literature.xml befindet sich der Inhalt, der über Java ausgelesen werden soll. Das root-Element ist literature. Dieses Element besteht aus mehreren Bücher welche sich aus Autoren, einem Titel, einer Auflage sowie einer ISBN Nummer zusammensetzt. Ein Buch kann selbstverständlich von mehreren Autoren geschrieben worden sein. Die Auflage eines Buches beinhaltet einen Verlag, die Auflage sowie das Veröffentlichungsjahr.
All diese Zusammengehörigkeiten sind nochmals in einer zusätzlichen Dokumenttypdefinitionsdatei (literatur.dtd) hinterlegt.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE literature SYSTEM "literature.dtd"> <literature> <book> <authors> <author> <firstName>Helmut</firstName> <lastName>Vonhoegen</lastName> </author> </authors> <title>Einstieg in XML</title> <edition> <publisher>Galileo Computing</publisher> <editionNo>2</editionNo> <publicationYear>2004</publicationYear> </edition> <ISBN>3-89842-488-X</ISBN> </book> <book> <authors> <author> <firstName>Dirk</firstName> <lastName>Ammelburger</lastName> </author> </authors> <title> XML - Grundlagen der Sprache und Anwendungen in der Praxis </title> <edition> <publisher>Hanser Verlag</publisher> <editionNo>1</editionNo> <publicationYear>2004</publicationYear> </edition> <ISBN>3-446-22562-5</ISBN> </book> <book> <authors> <author> <firstName>Ed</firstName> <lastName>Tittel</lastName> </author> <author> <firstName>Frank</firstName> <lastName>Boumphrey</lastName> </author> </authors> <title>XML für Dummies</title> <edition> <publisher>mitp</publisher> <editionNo>2</editionNo> <publicationYear>2002</publicationYear> </edition> <ISBN>3-8266-2942-6</ISBN> </book> <book> <authors> <author> <firstName>Charles F.</firstName> <lastName>Goldfarb</lastName> </author> <author> <firstName>Paul</firstName> <lastName>Prescod</lastName> </author> </authors> <title>Das XML-Handbook</title> <edition> <publisher>Addison-Wesley</publisher> <editionNo>1</editionNo> <publicationYear>2000</publicationYear> </edition> <ISBN>3-8273-1712-6</ISBN> </book> </literature>
literature.dtd
Die Dokumenttypdefinitionsdatei beschreibt den Inhalt der literatur.xml. Hierbei werden die einzelnen zugehörige Elemente jeweils überschaubar dargestellt.
<?xml version="1.0" encoding="ISO-8859-1"?> <!ELEMENT literature (book*)> <!ELEMENT book (authors, title, edition, ISBN)> <!ELEMENT authors (author+)> <!ELEMENT author (firstName, lastName)> <!ELEMENT firstName (#PCDATA)> <!ELEMENT lastName (#PCDATA)> <!ELEMENT title (#PCDATA)> <!ELEMENT edition (publisher, editionNo, publicationYear)> <!ELEMENT publisher (#PCDATA)> <!ELEMENT edition (#PCDATA)> <!ELEMENT publicationYear (#PCDATA)> <!ELEMENT ISBN (#PCDATA)>
Author.java
In dem Paket model werden die einzelnen Fachklassen hinterlegt. Da der Aufbau der einzelnen Objekte bekannt ist, wurden hierzu drei verschiedene Objektklassen erstellt. In der toString() Methode werden Vor- und Nachname ausgegeben.
package model; public class Author { private String firstName; private String lastName; public Author(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String toString() { return firstName + " " + lastName; } }
Book.java
Diese Klasse enthält alle relevanten Attribute eines Buches. Da ein Buch durchaus mehrere Autoren haben kann, werden diese in einem Vector gespeichert. In der toString() Methode werden letztendlich die vorhandenen Informationen über das Buch ausgegeben. Besteht ein Buch aus mehreren Autoren, werden diese durch ein Komma getrennt.
package model; import java.util.Vector; public class Book { private String title; private Vector authores; private String publisher; private int edition; private int publicationYear; private String isbn; public Book(String title, String publisher, int edition, int publicationYear, String isbn) { this.title = title; this.authores = new Vector(); this.publisher = publisher; this.edition = edition; this.publicationYear = publicationYear; this.isbn = isbn; } public void addAuthor(Author a) { authores.add(a); } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Vector getAuthores() { return authores; } public void setAuthores(Vector authores) { this.authores = authores; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getEdition() { return edition; } public void setEdition(int edition) { this.edition = edition; } public int getPublicationYear() { return publicationYear; } public void setPublicationYear(int publicationYear) { this.publicationYear = publicationYear; } public String getIsbn() { return isbn; } public void setIsbn(String isbn) { this.isbn = isbn; } public String toString() { String author = ""; for (int i = 0; i < authores.size(); i++) { author += authores.get(i).toString(); if (i < authores.size() - 1) { author += ", "; } } return author + "\n" + "'" + title + "'" + "\n" + publisher + ", " + edition + ". Auflage (" + publicationYear + ")" + "\n" + "ISBN " + isbn; } }
Literature.java
Die Literature Klasse besteht aus dem Großteil des XML-Dokumentes. In diesem Objekt sind die Bücher mit den zugehörigen Autoren gespeichert. Der Rückgabewert der toString() Methode listet das XML-Dokument formatiert aus.
package model; import java.util.Vector; public class Literature { private Vector books; public Literature() { books = new Vector(); } public void addBook(Book b) { books.add(b); } public Vector getBooks() { return books; } public String toString() { String result = ""; for (int i = 0; i < books.size(); i++) { result += books.get(i) + "\n" + "\n"; } return result; } }
XMLinObject.java
XMLinObject spiegelt den Verlauf der Objekterstellung der in der XML Datei enthaltenen Elemente wieder. Aus chronologischer Sicht wird zunächst ein Litereratur Objekt erstellt und anschließend die einzelnen Bücher mit den Autoren gefüllt. Die Methode createLiterature() muss anschließend lediglich aufgerufen werden um die XML Datei auszulesen. Dies geschieht in XMLLiterature.
package dataStorage; import model.Author; import model.Book; import model.Literature; import org.w3c.dom.Element; import org.w3c.dom.NodeList; /** * Klasse zur Erzeugung der model-Objekte aus der XML Datei */ public class XMLinObject { /** * Erzeugt ein Literatur-Objekt aus dem entsprechenden XML-Knoten. */ public static Literature createLiterature(Element literatureXML) { Literature literature = new Literature(); // Wir holen uns das Element 'book' aus dem XML-DOM .. NodeList bookList = literatureXML.getElementsByTagName("book"); // .. und fügen alle Bücher der Literaturliste hinzu for (int i = 0; i < bookList.getLength(); i++) { Element currentBook = (Element) bookList.item(i); // neues Buch aus dem XML-Knoten erstellen Book book = createBook(currentBook); // Buch dem Literaturvektor hinzufügen literature.addBook(book); } return literature; } /** * Erzeugt ein Buch-Objekt aus dem entsprechenden XML-Knoten. */ public static Book createBook(Element bookXML) { // Wir holen uns Inhalt des 'title' Knotens (die restlichen Informationen // werden analog aus dem XML Knoten gezogen) String title = bookXML.getElementsByTagName("title").item(0) .getTextContent().trim(); String publisher = bookXML.getElementsByTagName("publisher").item(0) .getTextContent().trim(); int edition = Integer.parseInt(bookXML.getElementsByTagName("editionNo") .item(0).getTextContent().trim()); int publicationYear = Integer.parseInt(bookXML .getElementsByTagName("publicationYear").item(0).getTextContent() .trim()); String isbn = bookXML.getElementsByTagName("ISBN").item(0).getTextContent().trim(); // das neue Buch wird mit den neuen Informationen erstellt Book buch = new Book(title, publisher, edition, publicationYear, isbn); // Nun ist der Autor an der Reihe NodeList authoreList = bookXML.getElementsByTagName("author"); for (int i = 0; i < authoreList.getLength(); i++) { // Autor holen und erstellen .. Element autor = (Element) authoreList.item(i); // .. und dem Buch hinzufügen buch.addAuthor(createAutor(autor)); } return buch; } /** * Erzeugt einen neuen Author aus dem XML-Knoten */ public static Author createAutor(Element autorXML) { // Hier wird der Vorname über die Methode getChildNodes() (Alternative zu // getElementsByTagName()) besorgt String firstName = autorXML.getChildNodes().item(0).getTextContent(); String lastName = autorXML.getChildNodes().item(1).getTextContent(); Author autor = new Author(firstName, lastName); return autor; } }
XMLLiterature.java
Dies ist wohl die entscheidende Datei. Für das Auslesen einer XML Datei wird eine factory, ein builder sowie ein document benötigt. Zuletzt kann das Dokument mit getDocumentElement() an die createLitererature() übergeben und anschließend ausgelesen werden.
package dataStorage; import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import model.Literature; import org.w3c.dom.Document; import org.xml.sax.SAXException; public class XMLLiterature { public static void main(String[] args) { try { // eine neue factory erstellen DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // Leerzeichen werden entfernt factory.setIgnoringElementContentWhitespace(true); // bevor ein 'Document' erstellt werden kann wird ein 'DocumentBuilder' benötigt DocumentBuilder builder = factory.newDocumentBuilder(); // Speicherort der XML-Datei File file = new File("src/xml/literature.xml"); Document document = builder.parse(file); // Erstellen eines Literatur-Objektes Literature literatur = XMLinObject.createLiterature(document.getDocumentElement()); // Ausgabe des XML-Dokumentes in Objekte System.out.println(literatur); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
Ergebnis
Helmut Vonhoegen 'Einstieg in XML' Galileo Computing, 2. Auflage (2004) ISBN 3-89842-488-X Dirk Ammelburger 'XML - Grundlagen der Sprache und Anwendungen in der Praxis' Hanser Verlag, 1. Auflage (2004) ISBN 3-446-22562-5 Ed Tittel, Frank Boumphrey 'XML für Dummies' mitp, 2. Auflage (2002) ISBN 3-8266-2942-6 Charles F. Goldfarb, Paul Prescod 'Das XML-Handbook' Addison-Wesley, 1. Auflage (2000) ISBN 3-8273-1712-6
vielen dank für das anschauliche Tutorial! Hat mir sehr geholfen.
evtl. könnte man noch ergänzen, wie man an Attribute in der XML kommt, aber eigentlich ist das dann auch schnell rausgefunden. Es ist ja einfach ein getAttribute(„xy“) statt ein getElementsBy…
Kann es sein, dass die XML-Datei nach der hier angegebenen DTD gar nicht valide ist…? Grundsätzlich schönes Tutorial, aber ich persönlich bin da sehr empfindlich, wenn kleinere Dinge in Tutorials falsch sind und man dann drüber stolpert.
Hallo Mandy,
aus welchem Grund sollte denn deiner Meinung nach die XML-Datei mit der hier verwendeten DTD-Datei nicht valide sein?
Also ich denke der Eintrag für das Element edition stimmt nicht. Bzw. glaube ich, dass dieser Eintrag:
eigentlich „edition“ heißen sollte, und das hier gelistete Kindelement edition eigentlich „editionNo“ sein muss. (dann wäre auch richtig, dass editionNo (#PCDATA) ist)
Gut, so schlimm ist das ja nicht und vermutlich stört es die Anwendung auch gar nicht. Mir ist nur aufgefallen, dass beim Nachvollziehen in eclipse Fehler angezeigt wurden. Und vielleicht war ich auch etwas gefrustet, weil ich schon einige JAXP-Tutorials durch habe und in jedem irgendwas nicht funktionierte. In diesem Fall war es für mich eigentlich nur leicht verwirrend.
Hallo Mandy,
du hast natürlich vollkommen Recht. Korrektur wurde entsprechend durchgeführt. Danke für den Hinweis.
Gruß
Simon
hallo Simon,
vielen dank für das tutorial, aber da ich in der Sache ganz neu
bin, würde ich gern mal wissen wie ich das alles über Ubuntu kompilieren kann?
vielen dank im vorraus!
liljane