2.4 Analyse von XML-Dokumenten Die EXtensible Markup Language ist eine formale Beschreibungssprache für hierarchisch strukturierte Daten. Einführung in die Spezifikation von XML: Auszug aus der kf. Grammatik von XML: document ::= prolog element Misc* prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' VersionInfo ::=... Misc ::= Comment PI S doctypedecl ::= '<!DOCTYPE' S Name ( S ExternalID)? S? ('[' ([ intsubset ']' S?)? S) '>' element ::= EmptyElemTag STag content ETag EmptyElemTag ::= '<' Name (S Attribute)* S? '/> ' STag ::= '<' Name (S Attribute)* S? '>' Attribute ::= Name Eq AttValue... Nichtterminal S bezeichnet Whitespace. 181
Beispiel: (XML-Dokument) Folgendes Beispiel stammt von www.onjava.com <?xml version="1.0"?> <!DOCTYPE catalog> <catalog library="somewhere"> <book> <author>author 1</author> <title>title 1</title> </book> <book> <author>author 2</author> <title>his One Book</title> </book> <magazine> <name>mag Title 1</name> <article page="5"> <headline>some Headline</headline> </article> <article page="9"> <headline>another Headline</headline> </article> </magazine> </catalog> 182
Aufgaben der Analyse von XML: Zentrale Aufgaben sind: lexikalische und kontextfreie Analyse Prüfen der Wohlgeformtheitsregeln, z.b.: - richtige Schachtelung ht der Elemente durch Start- und Endetags - Eindeutigkeit von Attributnamen - Definiertheit von Entitätsreferenzen - usw. Prüfen der Gültigkeit bzgl. Regeln der DTD oder des XML-Schemas. Vergleich zur Analyse von Programmen: Einfache kontextfreie Analyse Einfache Namensanalyse Keine Typinferenz Gültigskeitsregeln können vom Dokument selbst definiert oder importiert werden. Abschätzung der Dokumentgröße schwierig; Dokumente können sehr groß sein. Meist sehr hohe Effizienz wichtig. 183
Parsen von XML-Dokumenten: Zwei standardisierte Techniken zur Anbindung des XML-Frontends/Parsers an die Anwendung: SAX - Simple API for XML Parsing: Registrieren eines Beobachters beim Parser Parser schickt Ereignisse an Beobachter, z.b. bei Start und Ende eines Elements Beobachter liefert Daten für die Anwendung Vorteile: - Dokumente müssen nie vollständig als Datenstruktur aufgebaut werden: problemlose Behandlung großer Dokumente - einfach und sehr effizient zu benutzen Nachteile: - Benutzer muss Datenstruktur zur Repräsentation des Dokuments selbst definieren. - Baumaufbau ist selbst zu programmieren. 184
DOM - Document Object Model: Baut einen Syntaxbaum auf, der alle Informa- tionen des Eingabedokuments in einer allgemeinen Datenstruktur verfügbar macht. Allgemeine Datenstruktur sollte ggf. in Datenstruktur transformiert werden, die den spezifischen Anforderungen der Anwendung gerecht wird. Vorteile: - Automatischer Aufbau einer standardisierten Datenstruktur. - ohne Weiteres zu benutzen Nachteile: - Entstehung einer aufwendigen Repräsentation, die möglicher Weise viele Aspektes enthält, die für aktuelles Dokument unwichtig sind. - Oft Anpassung an spezielle Dokumentstruktur notwendig - speicheraufwendig und bei großen Dokumenten nur bedingt einsatzfähig und langsam. 185
Parsen mit JAXP: SAX-Parser Beobachter des Parsers müssen die Schnittstelle org.xml.sax.contenthandler implementieren. Die Klasse org.xml.sax.helpers.defaulthandler enthält für alle Methoden von ContentHandler eine triviale Implementierung, so dass deren Subklassen nur die benutzten Methoden realisieren müssen. Beispiel: (Beobachterklasse für SAX) class SaxCatalogUnmarshaller extends DefaultHandler { public void startelement( String uri, String localname, String qname, Attributes attribs ){... } public void endelement( String uri, String localname, String qname ) {... } } public void characters( char[] data, int start, int length ) {... } 186
Will man als Beobachter einen Syntaxbaum aufbauen, muss man: - die Datenstruktur für den Syntaxbaum definieren, - eine kellerartige Verwaltung für die zu lesenden Elemente realisieren, - den Syntaxbaum ausgehend von der Kellerinfor- mation bei Erhalten der Nachrichten endelement sukkzessive aufbauen. Anwendungsbeispiel: i public class Driver { public static void main(string[] args)...{ InputSource src = new InputSource( new FileInputStream(... ) ); // 1. Beobachter erzeugen SaxCatalogUnmarshaller saxums = new SaxCatalogUnmarshaller(); // 2. Parser/Reader erzeugen XMLReader rdr = XMLReaderFactory. createxmlreader( "org.apache.xerces. parsers.saxparser SAXParser" ); // 3. Beobachter registrieren rdr.setcontenthandler( saxums ); // 4. Starten des Einlesens rdr.parse( src );... } } 187
Parsen mit JAXP: DOM-Parser Zur Repräsentation von Syntaxbäumen wird eine allgemeine Datenstruktur verwendet. Zentral ist dabei der Schnittstellentyp Node. Hier eine kleiner Auszug: interface Node { Node appendchild(node newchild) ; Node clonenode(boolean deep); NamedNodeMap getattributes(); NodeList getchildnodes(); Node getfirstchild(); Node getlastchild(); String getlocalname(); String getnamespaceuri(); Node getnextsibling(); String getnodename(); short getnodetype(); String getnodevalue();... // und viele Methoden mehr } 188
Der Typ Document repräsentiert Syntaxbäume für vollständige XML-Dokumente: interface Document extends Node {... } Da der Syntaxbaumaufbau unabhängig von der Anwendung ist, kann er ohne Weiteres gestartet werden: Anwendungsbeispiel: public class Driver { public static void main(string[] args)...{ InputSource src = new InputSource( new FileInputStream(... ) ); // 1. Parser/Reader erzeugen DOMParser prsr = new DOMParser(); // 2. Starten des Einlesens prsr.parse( p src ); // 3. Zugriff auf Syntaxbaum Document doc = prsr.getdocument(); // 4. Weitere Verarbeitung... } } 189