Berner Fachhochschule Software Schule Schweiz JDOM http://www.jdom.org/ Beatrice Amrhein Oktober 06 1 Motivation JDOM ist ein Open Source, Baumbasiertes, Java API zum Parsen, Erzeugen, Verarbeiten und Speichern von XML Dokumenten. JDOM ist in und für Java entwickelt und benutzt die üblichen Java Konventionen und deren Class Library. So werden zum Beispiel die Kinder eines Elementes in einer Java-Liste gespeichert. JDOM implementiert keinen eigenen Parser, sondern benutzt einen SAX Parser zum Einlesen und Aufbauen von JDOM Modellen. Ein einmal (ins Memory) eingelesenes Dokument (egal ob von einem File eingelesen oder vom Java Programm neu erzeugt) ist beliebig veränderbar. Der gesamte Dokument Baum kann gelesen und überschrieben werden. Ist die Arbeit am Dokument beendet ist das Schreiben der Daten in ein XML Dokument mit JDOM sehr einfach. 1.1 Vergleich von DOM zu JDOM Das org.w3c.dom Java Package stellt Interfaces für das Document Object Model (DOM, Document Object Model, W3C Recommendation 07 April 2004) zur Verfügung. Diese sind aber nicht sehr komfortabel zu benutzen: Die wichtigsten Interfaces von org.w3c.dom Attr Das Attr Interface für die Attribute in einem Element Objekt. CDATASection Das Interface für CDATA Abschnitte. CharacterData Das Interface für Text Daten im DOM. Comment Abgeleitet von CharacterData für Kommentare innerhalb <!--' und '-->'. Document Das Document Interface als Container für den ganzen XML Baum. Element Das Element Interface für XML Elemente. Node Das Node Interface ist der wichtigste Datentyp für das Document Object Model. Alle XML Knoten (Elemente, Text-Knoten, ...) sind in erster Linie vom Typ Node. NodeList Das NodeList Interface dient als Abstraktion für eine Liste von Notes, ohne zu definieren, wie diese Liste implementiert warden soll. Text Das Text Interface ist abgeleitet von CharacterData und dient zum Bearbeiten von Text in Elementen oder Attributen. Das Node Interface bietet die Basis zum Aufbau eines DOM Baumes: { ... Node thisNameNode = thisCoffeeNode.getFirstChild(); String data = thisNameNode.getFirstChild().getNodeValue(); Node newHelloNode = document.createElement("Hello"); Text tnNode = document.createTextNode("World"); newNameNode.appendChild(tnNode); ... } JDom ist kein Wrapper für DOM. Es bietet vielmehr je eine Klasse für alle XML Knoten (Attribute, Kommentare, Elemente, Text-Knoten, ...) und Methoden zum Verarbeiten derselben: 2 Die wichtigsten Klassen von jdom Attribute Ein XML Attribute. CDATA Eine XML CDATA Abschnitt. Comment Ein XML Kommentar. Content Basis Klasse für JDOM alle Objekte. DefaultJDOMFactory Erzeugt Standard JDOM Klassen (Element, Document, Comment, etc). DocType Eine XML DOCTYPE Deklaration. Document Ein XML Dokument. Element Ein XML Element. EntityRef Eine XML Entity Referenz. Text Text basierter XML Inhalt. Das Arbeiten mit JDom ist viel natürlicher und direkter als über das DOM Interface: while (i.hasNext()) { Element person = (Element) i.next(); Element name = person.getChild("name"); Attribute date = person.getAttribute(“date“); ... } 3 2 Das JDom Package Die JDOM Packages org.jdom org.jdom.adapters org.jdom.filter org.jdom.input org.jdom.output org.jdom.transform org.jdom.xpath 2.1 Die wichtigsten Klassen von JDom Die Klasse Attribute CDATA Comment DocType Docment Element Text EntityRef Namespace Verifier Zum Bearbeiten von Æ Æ Æ Æ Æ Æ Æ XML Attributen CDATA Strings Kommentaren XML DOCTYPE Deklaration. XML Dokumenten XML Element-Knoten XML Text Knoten definiert eine XML Entity Reference definiert einen XML Namespace Testen von Wohlgeformtheit und Gültigkeit Die Document Klasse Erzeugen eines neuen JDom-Documents mit Root Element root. new Document(Element root) Weitere Methoden get/setDocType() get/setRootElement () liest / (er-) setzt den DTD liest / (er-) setzt das RootElement Die Document Klasse enthält die Methoden zum Lesen und Verarbeiten der Dokument-Struktur: Document addContent(Comment c) java.util.List getContent() java.util.List getContent(Filter filter) Element getRootElement() boolean hasRootElement() boolean removeContent(Comment c) Document setContent(java.util.List c) ... 4 Die wichtigsten Befehle der Klasse Element: Die Klasse Element new Element( String name ) Erzeugen eines neuen Elements: Element getChild (java.lang.String name, Namespace ns) java.util.List getChildren() das erste Kind (mit diesem Namen) die Liste aller Kinder Element setContent (Content child) (er-) setze Element Inhalt Element addContent(int index, Content child) ergänze den Inhalt des Elements. Element set-/getAttribute( ... ) Die Klasse Attribute Erzeugen eines neuen Attributes: new Attribute( String name, String value ) Weitere Methoden set/getValue() lesen / ersetzen des Attribut-Werts set/getName() lesen / ersetzen des Attribut-Namens String getName() Attribute getAttribute( . . . ) Element setAttribute( . . . ) List getAttributes() String getAttributeValue( . . .) Element getParent() String getText() Element setText(String text) String getTextTrim() boolean hasChildren() Element getChild( . . . ) List getChildren( . . . ) String getChildText( . . . ) String getChildTextTrim( . . . ) Element addContent( . . . ) Element setContent( . . . ) Die wichtigsten Methoden der Klasse Attribute: String getName() Attribute setName(String name) Attribute setValue(String value) String getValue() int getIntValue() boolean getBooleanValue() float getFloatValue() ... Namespace getNamespace() Element getParent() ... 5 3 Beispiele 3.1 Erzeugen eines XML Dokuments Gesucht ist ein JDOM Dokument, welches (zum Beispiel beim Schreiben in ein in ein File mit dem XMLOutputter) genau diese XML Struktur erzeugt. <?xml version="1.0"?> <myRoot>Hello World!</myRoot> Das entsprechende JDOM Document kann auf die folgende Art erzeugt werden: Element root = new Element("myRoot"); root.setText("Hello World!"); Document doc = new Document(root); Falls zusätzlich im Root Element ein Attribut eingefügt werden soll <?xml version="1.0"?> <myRoot date="5.9.02"> Hello World! </myRoot> muss das Document wie folgt erweitert werden Element root = new Element("myRoot"); root.setText("Hello World!"); root.setAttribute("date", "5.9.02"); Document doc = new Document(root); Weitere Elemente können dann mit addContent() eingefügt werden: Element root = new Element("myRoot"); Element ele1 = new Element("myElem"); Element ele2 = new Element("myElem"); ele1.setText("Hello!"); ele2.setText("World!"); root.addContent(ele1); root.addContent(ele2); root.setAttribute("date", "5.9.02"); Document doc = new Document(root); <?xml version="1.0"?> <myRoot date="5.9.02"> <myElem>Hello</myElem> <myElem>World!</myElem> </myRoot> 6 3.2 Schreiben des JDom Baumes in ein XML File Das so erzeugte Document kann nachher sehr einfach schön formatiert in ein File geschrieben werden. FileOutputStream out = new FileOutputStream(file); // use pretty format XMLOutputter serializer = new XMLOutputter(Format.getPrettyFormat()); serializer.output(doc, out); 3.3 Einlesen / Bearbeiten von XML Files Im umgekehrten Fall, also wenn bereits ein XML Dokument vorliegt, kann dieses mit Hilfe des SAX Builders in ein JDom Document eingefüllt werden: 1. Erzeugen eines SAXBuilder 2. build() aufrufen, um ein Document Object zu erzeugen 3. Bearbeiten des Dokuments mit den Methoden der Klassen Document, Element class, Attribute, ... SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(inFile); Element root = doc.getRootElement(); 3.4 Beispiel: Validieren eines XML Dokumentes mit JDOM import org.jdom.*; import org.jdom.input.*; import java.io.*; public class JDOMValidator { public static void main(String[] args) { if (args.length == 0) { // command line should offer URIs or file names System.out.println("Usage: java JDOMValidator URL"); return; } SAXBuilder builder = new SAXBuilder(true); // Turn on validation try { Document doc = builder.build(args[0]);. System.out.println(args[0] + " is valid."); // No error } catch (JDOMException e) { // indicates a well-formedness or validity error System.out.println(args[0] + " is not valid. \n" + e.getMessage()); } catch (Exception e) { System.out.println("Could not check " + args[0] + ": “ + e.getMessage()); } } } 7 3.5 Konvertieren von DOM Dokumenten nach JDOM Das package org.jdom.input besitzt eine Klasse DomBuilder, welcher zum Parsen eines DOM Dokuments verwendet werden kann. // @param domDoc the DOM document public org.jdom.Document convert(org.w3c.dom.Document domDoc) throws JDOMException, IOException { // Create new DOMBuilder, using default parser org.jdom.input.DOMBuilder builder = new org.jdom.input.DOMBuilder(); } // read dom document into jdom document org.jdom.Document jdomDoc = builder.build(domDoc); return jdomDoc; 3.6 Verwenden von XPath in JDOM Mit Hilfe des jdom.xpath packages können wir auch die Methode getElementByID von DOM nachbauen. xpath.selectSingleNode gibt uns das erste (und falls der Attribut-Wert eine ID ist das einzige) Element unter dem gesuchten Pfad zurück. Der Pfad, welchen wir hier benutzen, lautet: path[attrName=’attrValue] was so viel bedeutet wie: alle Elemente unter dem Pfad path, welche ein Attribut namens attrName mit dem Wert attrValue besitzen. /** * Gets the (first) element found at path 'path' with a given attribute value. * @param path -- the search path. * @param attrName -- the name of the attribute. * @param attrValue -- the value of the attribute. * @param context -- the element context (e.g. the root Element). * @return the first element found with a given attribute value. * @throws JDOMException */ private Element getElementByID(String path, String attrName, String attrValue, Element context) throws JDOMException { String pathString = path + "[@" + attrName + "='" + attrValue + "']"; XPath xpath = XPath.newInstance(pathString); return (Element) xpath.selectSingleNode(context); } 8