Java und XML Tutorial

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