1 Überblick ■ XML-APIs für Java ■ SAX Architekturen für verteilte Internetdienste ■ DOM ■ Java: JDOM, dom4j, StAX ■ Validierendes Parsen Übung 1: XML + APIs [email protected] © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 2 XML-APIs für Java 3 Simple API for XML (SAX) ■ Konzept ■ Event-Driven Parsing ◆ Herstellerunabhängige Schnittstelle ■ Push von „Elementen“ des Dokuments an Handler ◆ Beliebige Implementierung ■ Zustandsloser Stream ohne Navigationsmöglichkeit • Auswahl zur Laufzeit: System Properties + Factories ■ Vorgehen ■ Packages: javax.xml, org.xml, org.w3c ◆ SAXParserFactory erzeugt SAXParser (package javax.xml.parsers) ■ DOM-Parser: Baum von Elementen des Dokuments ◆ Dessen SAXReader ruft diverse Handler auf ◆ Sprachunabhängiges Document Object Model ◆ ContentHandler, ErrorHandler, DTDHandler, EntityResolver, ... ◆ Eigenen von DefaultHandler ableiten und ergänzen ■ SAX-Parser: Stream Pushing ◆ Simple API for XML ■ StAX-Parser: Stream Pulling ■ JDOM-Parser: DOM à la Java ■ Aktueller Parser im Java SDK: Apache-Xerces © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 1.1 1.2 © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 3 Simple API for XML (SAX) 3 Simple API for XML (SAX) ■ Programmierung ■ Implementierung eines eigenen Handlers ◆ DefaultHandler ableiten public { void void void ◆ Ggf. weitere Handler für CDATA, DTD-Elemente, ... ◆ Factory, Parser initialisieren und starten class MyHandler extends DefaultHandler startDocument() throws SAXException {...} endDocument () ... startElement (String namespaceURI, String sName, String qName, Attributes attrs) ... void endElement (String namespaceURI, String sName, String qName) ... void characters (char[] buf, int offset, int len) ... ... void ignorableWhitespace (char[] buf, int offset, int len) ... void processingInstruction(String target, String data) ... void setDocumentLocator (Locator l) ... ... void warning (SAXParseException e) ... void error (SAXParseException e) ... ◆ Ggf. validierendes Parsen, Namespace-Awareness konfigurieren } 1.3 © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 1.4 © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 4 Document Object Model (DOM) 4 Document Object Model (DOM) ■ Parsing läuft automatisch durch und erzeugt DOM-Baum ■ Vorgehen ◆ DocumentBuilderFactory erzeugt DocumentBuilder ■ Navigation auf Dokumentbaum von mäßig getypten Knoten ◆ Document per newDocument() oder Parsing erzeugen ■ Sprachunabhängige API ◆ Root-Element: Document.getDocumentElement() ◆ Alles ist ein Knoten (Element, Attribut, Text, ...) ◆ Node-API mit nodeValue(), nodeType(), nodeName() ◆ Schwerfällig ◆ Nervig: getNodeType()==Node.ELEMENT NODE Beispiel: <e>bla<e> Node child = data.getFirstChild(); while(child!=null) { if (child.getNodeType() == Node.ELEMENT_NODE) { Element e = (Element) child; ... } else ... child = child.getNextSibling(); } ◆ <e>: nodeType()=”e”, nodeValue()=null ◆ bla: nodeType()=”#text”, nodeValue()=”bla” ◆ getElementsByTagName() ist transitiv, nicht auf direkte Subknoten beschränkt ◆ getChildNodes() liefert alle Subknoten, nicht nur Subelemente © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 1.5 1.6 © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 4 Document Object Model (DOM) 4 Document Object Model (DOM) ■ Parsen ■ Wichtige Methoden (Auswahl) ◆ org.w3c.dom.Node DocumentBuilderFactory factory; DocumentBuilder builder; Document doc; • appendChild, removeChild, getTextContent, getParentNode, getOwnerDocument, getNodeName/Type/Value, get/hasAttributes, getFirst/LastChild, getNextSibling, getChildNodes factory = DocumentBuilderFactory.newInstance(); ◆ org.w3c.dom.Document builder = factory.newDocumentBuilder(); builder.setErrorHandler(new org.xml.sax.ErrorHandler() {...}); doc • getDocumentElement, createAttribute, createElement, createTextNode, getElementsByTagName ◆ Ableitungen: org.w3c.dom.Element, .Attr, .Comment, .Text, ... = builder.parse( new File("data.xml") ); 1.7 © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 1.8 © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 5 Java: JDOM, dom4j, StAX 5 Java: JDOM, dom4j, StAX ■ JDOM ■ JDOM Beispiel ◆ Java-OOP DOM-Zugriff ◆ Packages org.jdom.** von http://www.jdom.org SAXBuilder builder = new SAXBuilder(true); ◆ Nutzt SAX/DOM-Parser, z.B. via org.jdom.input.SAXBuilder Document doc = builder.build("data.xml"); Element root = doc.getRootElement(); ◆ Konkrete Klassen anstatt Interfaces ◆ Analoge Methoden zum Manipulieren, Validieren println("Element: "+root.getName()); for (Attribute a: root.getAttributes()) println("- Attribute "+a.getName()+"="+a.getValue()); for (Element e: root.getChildren()) println("- Element "+e.getName()); ◆ JSR-102 javax.xml.tree ■ Alternative dom4j ◆ Schneller/kleiner ◆ Schnelle Traversierung großer Dokumente ◆ Auf Interfaces aufbauende Implementierung ◆ XPath-Integration 1.9 © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 1.10 © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 5 Java: JDOM, dom4j, StAX 6 Validierendes Parsen ■ XML-Pull-Parsing: JSR-173 javax.xml.stream ■ ... am Beispiel von SAX: String VALIDATE = "http://xml.org/sax/features/validation"; String VAL_XSD = "http://apache.org/xml/features/validation/schema"; URL u = new URL("data.xml"); InputStream in = u.openStream(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLStreamReader parser = factory.createXMLStreamReader(in); for (int event = parser.next(); event != XMLStreamConstants.END_DOCUMENT; event = parser.next()) { switch (event) { case XMLStreamConstants.START_ELEMENT: case XMLStreamConstants.END_ELEMENT: parser.getLocalName(); break; case XMLStreamConstants.CDATA: case XMLStreamConstants.CHARACTERS: parser.getText(); break; } } parser.close(); DefaultHandler hr = new Handler(); XMLReader xr = XMLReaderFactory.createXMLReader(); xr.setFeature(VALIDATE, true); xr.setFeature(VAL_XSD, true); xr.setContentHandler(hr); xr.setErrorHandler(hr); FileReader r = new FileReader(filepath); xr.parse(new InputSource(r)); 1.11 © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 7 Aufgabe ■ Implementierung eines einfachen SAX-Parsers ◆ Verwenden des DefaultHandler ◆ Ausgabe der Namespaces ◆ Ausgabe Präfixe ◆ Ausgabe Events ■ Was ist ein DTDHandler / EntityResolver ■ Unterschied DefaultHandler vs. DefaultHandler2 ■ Implementierung eines einfachen DOM-Parsers ◆ Ausgabe der Knotentypen ◆ Ausgabe der Attribute ■ Welchen Parser in welcher Situation? 1.13 © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/ 1.12 © 2006, Holger Schmidt, Verteilte Systeme, Univ. Ulm, [u1.fm, 2006-05-05 09.37] http://www-vs.informatik.uni-ulm.de/teach/ss06/avid/