Transformation von XML-Dokumenten XML-Schnittstellen: SAX, DOM, XML Pull Parsing Timo Terletzki 03.11.2004 Übersicht 1. Motivation 2. XML Parser für Java 3. Document Object Model 4. Simple API for XML 5. SAX vs. DOM 6. XML Pull Parsing 7. Zusammenfassung 1. Motivation Ziel: Informationen aus XML Dokumenten auslesen - es ist möglich XML Dokumente mit einem Textfile Reader auszulesen - es ist sehr aufwendig einen solchen XML-File Reader zu implementieren - der XML-File Reader muss für jedes Programm neu geschrieben werden W3C legt einen Standard für XML-File Reader fest 2. XML Parser für Java XML Parser für Java: - ermöglicht den Zugriff auf Informationen in einem XML Dokument - Informationen können direkt in Java Objekte konvertiert werden, oder anderweitig verarbeitet werden - wird von vielen Firmen kostenlos bereitgestellt, z. B. Sun, Datachannel, IBM, ... - kann vom Programmierer implementiert werden (optional) 3. Document Object Model Übersicht • Document Object Model • DOM XML Parser • Document Object Model API • Document Object • Zusammenfassung • Beispiel 3.1 DOM – Document Object Model Anforderungen an das Document Object Model: - alle Informationen aus dem XML Dokument müssen angesteuert und geändert werden können - Navigation von Element zu Element muss ermöglicht werden - Elemente und Attribute müssen abgefragt werden können - grundlegende Funktionen, wie z.B. getfist und getnext, müssen bereitgestellt werden 3.2 DOM – DOM XML Parser DOM XML Parser für Java: - konvertiert ein XML Dokument in einen Objektbaum - übernimmt das Lesen und Speichern der Daten aus dem XML Dokument - speichert die Daten als ein Document Object - muss die Document Object Model API implementieren - wird vom Programmierer nicht implementiert - wird auch für andere Programmiersprachen bereitgestellt 3.3 DOM – Document Object Model API Document Object Model API (Java): - ist eine Sammlung von Java Interfaces, vergleichbar mit dem Swing Component Model - die Interfaces müssen vom XML Parser implementiert werden, damit Daten bearbeitet werden können - enthält keine Information aus dem XML-File - ermöglicht hierarchischen Zugriff auf das Document Object - ermöglicht das Ändern, Löschen und Neuanlegen von Knoten 3.3 DOM – Document Object Model API Es gibt noch weitere Interfaces, z.B. Comment, Text und ProcessingInstruction Quelle: „Introduction to DOM“ www.developerlife.com 3.4 DOM – Document Object Document Object: - enthält einen Baum, der die Struktur des XML-Files darstellt - die Knoten enthalten die Information des XML-Files - jeder Knoten enthält Informationen wie Knotenname, Knotenwert und ggf. Kinderknoten - das Document Object ist der Wurzelknoten (von Knoten abgeleitet) - kann mit Hilfe der DOM API gelesen und bearbeitet werden 3.4 DOM – Document Object Quelle: „Introduction to DOM“ www.developerlife.com 3.5 DOM – Zusammenfassung Quelle: „Introduction to DOM“ www.developerlife.com 3.6 DOM – Beispiel DOM Objekt aus XML File erzeugen: Sun XML Parser import com.sun.xml.tree.*; import org.w3c.dom.*; try { String url = "http://.../AddressBook.xml"; Document doc = XmlDocumentBuilder.createXmlDocument(url); } catch(Exception e){} 3.6 DOM – Beispiel DOM Objekt aus XML File erzeugen: IBM XML Parser import com.ibm.xml.parser.*; import org.w3c.dom.*; try { URL u = new URL("http://.../AddressBook.xml"); InputStream i = u.openStream(); Parser ps = new Parser(„IBM XML Parser"); Document doc = ps.readStream(i); } catch( Exception e ){} 3.6 DOM – Beispiel Quelle: „XML and Java Tutorial, Part I “ www.developerlife.com 3.6 DOM – Beispiel “\r“ = Zeilenvorschub Quelle: „XML and Java Tutorial, Part I “ www.developerlife.com 3.6 DOM – Beispiel Knoten auslesen: NodeList listOfPersons = doc.getElementsByTagName( "PERSON" ); int numberOfPersons = listOfPersons.getLength(); if (numberOfPersons > 0 ){ Node firstPersonNode = listOfPersons.item( 0 ); if ( firstPersonNode.getNodeType() == Node.ELEMENT_NODE ){ Element firstPersonElement = (Element)firstPersonNode; } } NodeList firstNameList = firstPersonElement.getElementsByTagName( "FIRSTNAME" ); 3.6 DOM – Beispiel Knoten auslesen: Element firstNameElement = firstNameList.item( 0 ); NodeList list = firstNameElement.getChildNodes(); String firstName = null; for (int i = 0 ; i < list.getLength() ; i ++ ){ String value = ((Node)list.item( i )).getNodeValue().trim(); if( value.equals("") || value.equals("\r") ){ continue; //keep iterating } else{ firstName = value; break; //found the firstName! } } 4. Simple API for XML Übersicht • SAX Parser • Object Model • Document Handler • Zusammenfassung • Beispiel 4.1 SAX – SAX Parser SAX Parser: - z.B. Sun TR2 XML Parser, IBM XML Parser for Java, OpenXML, ... - muss die Simple API for XML implementieren - liest das XML Dokument und feuert Ereignisse (Events) - die Reihenfolge der gefeuerten Events ist sehr wichtig - Events werden gefeuert: - am Anfang und am Ende des XML Dokuments - wenn Knoten Tags geöffnet und geschlossen werden - wenn Knotenwerte ausgelesen werden - Speichert keine Informationen aus dem XML Dokument 4.2 SAX – Object Model Object Model: - SAX hat kein Object Model - der Programmierer muss sich selber um die Verarbeitung der Informationen kümmern - der Programmierer kann sein eigenes Object Model erstellen (optional) - der Programmierer hat volle Kontrolle über das Speichern von Informationen 4.3 SAX – Document Handler Document Handler: - ist ein Listener für die im SAX Parser gefeuerten Events und muss sich beim SAX Parser als solcher registrieren - wird bei jedem Event vom SAX Parser aufgerufen - ist für die Verarbeitung der gelesenen Informationen zuständig - legt ggf. Instanzen von Objekten aus dem Object Model an - muss die Reihenfolge der gefeuerten Events beachten 4.3 SAX – Document Handler Quelle: „Introduction to DOM“ www.developerlife.com 4.4 SAX – Zusammenfassung Zusammenfassung: - es gibt kein vorgegebenes Object Model - SAX Parser liest das Dokument aus und feuert Events - die Reihenfolge der gefeuerten Events ist für den Document Handler sehr wichtig - Document Handler ist Listener für die gefeuerten Events - Document Handler ist für die Verarbeitung der gelesenen Informationen zuständig 4.5 SAX – Beispiel XML Dokument: <?xml version = "1.0"?> <addressbook> <person> <lastname>Timo</lastname> <firstname>Terletzki</firstname> <email>[email protected]</email> </person> </addressbook> 4.5 SAX – Beispiel Object Model: AdressBook List persons getSize() addPerson(Person a) getPerson(int i) deletePerson(int i) toXML() Person String firstname String lastname String email get-/set-Methoden() toXML() 4.5 SAX – Beispiel Document Handler: import java.io.*; import org.xml.sax.*; import org.xml.sax.helpers.ParserFactory; import com.sun.xml.parser.Resolver; public class SaxAddressBookHandler extends HandlerBase{ private AddressBook ab = new AddressBook(); private Person p = null; private String currentElement = null; public AddressBook getAddressBook(){ return ab; } 4.5 SAX – Beispiel Document Handler: public void startElement( String name , AttributeList atts ){ if( name.equalsIgnoreCase("LASTNAME") ) { currentElement = "LASTNAME"; } else if( name.equalsIgnoreCase("FIRSTNAME") ) { currentElement = "FIRSTNAME"; } else if( name.equalsIgnoreCase("COMPANY") ) { currentElement = "COMPANY"; } else if( name.equalsIgnoreCase("EMAIL") ) { currentElement = "EMAIL"; } else if( name.equalsIgnoreCase("PERSON") ) { p = new Person(); } } 4.5 SAX – Beispiel Document Handler: public void characters( char ch[], int start, int length ){ String value = new String( ch , start , length ); if(!value.trim().equals("")) { if( currentElement.equalsIgnoreCase("FIRSTNAME") ) { p.setFirstName( value ); } else if( currentElement.equalsIgnoreCase("LASTNAME") ) { p.setLastName( value ); } else if( currentElement.equalsIgnoreCase("COMPANY") ) { p.setCompany( value ); } else if( currentElement.equalsIgnoreCase("EMAIL") ) { p.setEmail( value ); } } 4.5 SAX – Beispiel Document Handler: public void endElement( String name ){ if( name.equalsIgnoreCase("PERSON") ) { ab.addPerson( p ); p = null; } } 4.5 SAX – Beispiel SAX Parser: import java.net.*; import java.io.*; import org.xml.sax.*; ... try{ InputStreamReader isr = new InputStreamReader( new FileReader( new File( "AddressBook.xml" )) ); InputSource is = new InputSource( isr ); DocumentHandler handler = new SaxAddressBookHandler(); String parserClassName = "com.sun.xml.parser.Parser"; org.xml.sax.Parser parser = org.xml.sax.helpers.ParserFactory. makeParser( parserClassName ); parser.setDocumentHandler( handler ); parser.parse( is ); AddressBook ab = handler.getAddressBook(); } catch(Throwable t){} ... 5. SAX vs. DOM DOM: - hierarchisches Object Model - Information wird in Knoten in einem Baum gespeichert - bewahrt die Reihenfolge der gelesenen Elemente SAX: - feuert eine Reihe von Events - es kann ein eigenes Object Model verwendet werden - es muss ein Document Handler geschrieben werden, der die Events abfängt und die Daten verarbeitet - ist zur Laufzeit schneller, da kein Objektbaum aufgebaut werden muss 5. SAX vs. DOM DOM eignet sich besser, wenn: - die Daten im XML Dokument immer wieder geändert werden müssen - eine Baumstruktur zur Navigation benötigt wird SAX eignet sich besser, wenn: - die Daten zu groß sind um sie als Baum gespeichert zu werden - nur Teile des XML Dokuments zur Verarbeitung verwendet werden 6. XML Pull Parsing Übersicht • Eigenschaften • Beispiel 6.1 XML Pull Parsing - Eigenschaften Eigenschaften: - sehr einfaches Interface - es gibt 5 Events: START_DOCUMENT, START_TAG, TEXT, END_TAG, END_DOCUMENT - Programmierer holt sich selber die Events selbst und verarbeitet diese in seinen Methoden - die Methode next() holt sich das nächste Event - ermöglicht Implementierung von sehr schnellen XML Parser 6.2 XML Pull Parsing - Beispiel import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; public static void main (String args[]) throws XmlPullParserException, IOException { XmlPullParserFactory factory = XmlPullParserFactory.newInstance( “XMLParserImplementierung“, null); XmlPullParser xpp = factory.newPullParser(); xpp.setInput ( new FileReader ( “AdressBook.xml“ ) ); this.processDocument(xpp); } 6.2 XML Pull Parsing - Beispiel public void processDocument(XmlPullParser xpp) { int eventType = xpp.getEventType(); do { if(eventType == XmlPullParser.START_DOCUMENT) { ... } else if(eventType == XmlPullParser.END_DOCUMENT) { ... } else if(eventType == XmlPullParser.START_TAG) { System.out.println(“Anfang “ + xpp.getName()); } else if(eventType == XmlPullParser.END_TAG) { System.out.println(“Ende “ + xpp.getName()); } else if(eventType == XmlPullParser.TEXT) { System.out.println(xpp.getText); } eventType = xpp.next(); } while (eventType != XmlPullParser.END_DOCUMENT); } 7. Zusammenfassung DOM: - DOM Parser liest das Dokument aus und speichert die Daten als Objektbaum - sehr leicht zu nutzen, da der Objektbaum mit Methoden der DOM API ausgelesen werden kann SAX: - SAX Parser liest Informationen aus und feuert Events - ein Document Handler muss implementiert werden, der die Informationen verarbeitet - es kann ein eigenes Object Model erstellt werden XMLPullParsing: - Events werden selbst geholt und verarbeitet - Volle Kontrolle über den Parse-Prozess Ende Vielen Dank für die Aufmerksamkeit.