Lernziele Welche verschiedenen XML-Parser gibt es? Was sind ihre Vor- und Nachteile? Was sind Schema-Übersetzer? Verarbeitung von XMLDokumenten © Klaus Schild, 2003 1 Grundlegende Architektur © Klaus Schild, 2003 2 Kategorien von Parser Pull- vs. Push-Parser: Wer hat die Kontrolle über das Parsen, die Anwendung oder der Parser? Zeichenkette XMLDokument Anwendung Serialisierer Parser Einschritt- vs. Mehrschritt-Parser (engl. one-step vs. multistep parsing): standardisierte APIs Wird das XML-Dokument in einem Schritt vollständig geparst oder Schritt für Schritt analysiert? Möglichst immer standardisierte APIs verwenden! Parser: Analysiert XML-Dokument und erstellt Parse-Baum mit Tags, Text-Inhalten und Attribut-Wert-Paaren als Knoten. Beachte: Kategorien unabhängig voneinander, können kombiniert werden Serialisierer: Generiert aus bestimmter Datenstruktur ein XMLDokument. © Klaus Schild, 2003 3 PullPull-Parser © Klaus Schild, 2003 4 PushPush-Parser nächste Einheit? Pull-Parser geparste Einheit Anwendung Push-Parser geparste Einheit Anwendung Anwendung hat die Kontrolle über das Parsen. Parser hat die Kontrolle über das Parsen. Analyse der nächsten syntaktischen Einheit muss von der Anwendung aktiv angefordert werden. Sobald der Parser eine syntaktische Einheit analysiert hat, benachrichtigt er die Anwendung und übergibt die entsprechende Analyse. Beachte: „Pull” bezieht sich auf die Perspektive der Anwendung. © Klaus Schild, 2003 Beachte: „Push” bezieht sich wiederum auf die Perspektive der Anwendung. 5 © Klaus Schild, 2003 6 1 XMLXML-Parser One-step Multi-step JAXP DOM Pull SAX-Parser Push SAX JAXP: Java API for XML Processing DOM: Document Object Model SAX: Simple API for XML © Klaus Schild, 2003 7 Simple API for XML (SAX) © Klaus Schild, 2003 8 Ereignisbasiertes Parsen mit SAX standardisiertes API für Mehrschritt-Push-Parsen von XML-Dokumenten SAX-Parser ursprünglich nur Java-API, inzwischen werden aber auch viele andere Sprachen unterstützt kein W3C-Standard, sondern de facto Standard Ereignis: neue syntaktische Einheit geparst Aufforderung zum Parsen Î http://www.saxproject.org/ Event Handler Anwendung © Klaus Schild, 2003 9 Beispiel für ereignisbasiertes Parsen <priceList> <priceList> <coffee> <coffee> <name> <name> MochaJava Java Mocha </name> </name> <price> <price> 11.95 11.95 </price> </price> </coffee> </coffee> </priceList> </priceList> © Klaus Schild, 2003 10 CallbackCallback-Methoden Parser ruft startElement(…,priceList,…) auf. Parser ruft startElement(…,coffee,…) auf. Parser ruft startElement(…,name,…) auf. Parser ruft characters("Mocha Java",…) auf. Parser ruft endElement(…,name,..) auf. Parser ruft startElement(…,price,…) auf. Parser ruft characters("11.95",…) auf. Parser ruft endElement(…,price,…) auf. Parser ruft endElement(…,coffee,…) auf. Parser ruft endElement(…,priceList,…) auf. startElement, endElement und characters werden Call-BackMethoden genannt, weil sie vom Parser aufgerufen werden. für jede syntaktische Struktur in XML eine eigene Callback-Methode Die Standard-Implementierung der Call-Back-Methoden (DefaultHandler) tut jeweils nichts. Standard-Implementierungen können aber entsprechend den Erfordernissen überschrieben werden. Sobald eine Einheit geparst wurde, wird die Anwendung benachrichtigt (Ereignisfluss). Beachte: Es wird kein Parse-Baum aufgebaut! © Klaus Schild, 2003 11 © Klaus Schild, 2003 12 2 Beispiel <priceList> <priceList> <coffee> <coffee> <name> <name> MochaJava Java Mocha </name> </name> <price> <price> 11.95 11.95 </price> </price> </coffee> </coffee> </priceList> </priceList> Ein SAXSAX-Parser Aufgabe: Gib des Preis von Mocha Java aus! SAXParserFactoryfactory factory==SAXParserFactory.newInstance(); SAXParserFactory.newInstance(); SAXParserFactory SAXParsersaxParser saxParser==factory.newSAXParser(); factory.newSAXParser(); SAXParser saxParser.parse("priceList.xml",handler); handler); saxParser.parse("priceList.xml", SAXParserFactory.newInstance() liefert eine SAXParserFactory. Hierfür benötigen wir zwei Dinge: Die Methode newSAXParser() liefert einen SAXParser mit einer Methode parse(). 1. einen SAX-Parser 2. passende CallbackMethoden priceList.xml: die zu parsende Datei (kann auch eine URL oder ein Stream sein) handler: Instanz von DefaultHandler, implementiert die Callback-Funktionen © Klaus Schild, 2003 13 © Klaus Schild, 2003 Exkurs: Factory Method Die CallbackCallback-Methoden Design Pattern aus „Design Patterns“ von Gamma, Helm, Johnson, Vlissides (1995) <priceList> <priceList> <coffee> <coffee> <name> <name> liefert ein Objekt MochaJava Java Mocha </name> </name> <price> <price> 11.95 11.95 </price> </price> </coffee> </coffee> </priceList> </priceList> Objekt ist Instanz einer abstrakten Klasse oder einem Interface. wird von mehreren Klassen implementiert Beispiel: Iterator i = list.iterator(); Beispiel: SAXParser saxParser = factory.newSAXParser(); Aufgabe: Gib den Preis von Mocha Java aus! © Klaus Schild, 2003 15 Die CallbackCallback-Methoden 14 Start startElement = name? inName characters = Mocha Java? inMochaJava startElement = price? inPrice characters = s? print(s) © Klaus Schild, 2003 16 Auf <name> name> warten publicvoid voidstartElement(..., startElement(...,String StringelementName, elementName,...) ...){{ public (elementName.equals("name")){ inName inName==true; true; }} ifif(elementName.equals("name")){ elseifif(elementName.equals("price") (elementName.equals("price")&& &&inMochaJava inMochaJava){ ){ else inPrice==true; true; inPrice inName==false; false; }}}} inName publicvoid voidstartElement(..., startElement(...,String StringelementName, elementName,...){ ...){ public (elementName.equals("name")){ inName inName==true; true; }} ifif(elementName.equals("name")){ elseifif(elementName.equals("price") (elementName.equals("price")&& &&inMochaJava inMochaJava){ ){ else inPrice==true; true; inPrice <name>MochaJava</name> Java</name> <name>Mocha inName==false; false; }}}} inName <price>11.95</price> <price>11.95</price> publicvoid voidcharacters(char characters(char[][]buf, buf,int intoffset, offset,int intlen) len){{ public Stringss==new newString(buf, String(buf,offset, offset,len); len); String (inName&& &&s.equals("Mocha s.equals("MochaJava")) Java")){{ ifif(inName inMochaJava==true; true; inMochaJava inName==false; false; }} inName elseifif(inPrice) (inPrice){{ else System.out.println("Theprice priceof ofMocha MochaJava Javais: is:""++s); s); System.out.println("The inMochaJava==false; false; inMochaJava inPrice==false; false; }} }} inPrice publicvoid voidcharacters(char characters(char[][]buf, buf,int intoffset, offset,int intlen) len){{ public Stringss==new newString(buf, String(buf,offset, offset,len); len); String (inName&& &&s.equals("Mocha s.equals("MochaJava")) Java")){{ ifif(inName inMochaJava==true; true; inMochaJava inName==false; false; }} inName elseifif(inPrice) (inPrice){{ else System.out.println("Theprice priceof ofMocha MochaJava Javais: is:""++s); s); System.out.println("The inMochaJava==false; false; inMochaJava inPrice==false; false; }} }} inPrice © Klaus Schild, 2003 17 © Klaus Schild, 2003 Start inName 18 3 Auf "Mocha Java" warten Auf <price> price> warten publicvoid voidstartElement(..., startElement(...,String StringelementName, elementName,...){ ...){ public (elementName.equals("name")){ inName inName==true; true; }} ifif(elementName.equals("name")){ elseifif(elementName.equals("price") (elementName.equals("price")&& &&inMochaJava inMochaJava){ ){ else inPrice==true; true; inPrice <name>MochaJava</name> Java</name> <name>Mocha inName==false; false; }}}} inName <price>11.95</price> <price>11.95</price> publicvoid voidstartElement(..., startElement(...,String StringelementName, elementName,...){ ...){ public (elementName.equals("name")){ inName inName==true; true; }} ifif(elementName.equals("name")){ elseifif(elementName.equals("price") (elementName.equals("price")&& &&inMochaJava inMochaJava){){ else inPrice==true; true; inPrice <name>MochaJava</name> Java</name> <name>Mocha inName==false; false; }}}} inName <price>11.95</price> <price>11.95</price> publicvoid voidcharacters(char characters(char[][]buf, buf,int intoffset, offset,int intlen) len){{ public Stringss==new newString(buf, String(buf,offset, offset,len); len); String (inName&& &&s.equals("Mocha s.equals("MochaJava")) Java")){{ ifif(inName inMochaJava==true; true; inMochaJava inName==false; false; }} inName elseifif(inPrice) (inPrice){{ else System.out.println("Theprice priceof ofMocha MochaJava Javais: is:""++s); s); System.out.println("The inMochaJava==false; false; inMochaJava inPrice==false; false; }} }} inPrice publicvoid voidcharacters(char characters(char[][]buf, buf,int intoffset, offset,int intlen) len){{ public Stringss==new newString(buf, String(buf,offset, offset,len); len); String (inName&& &&s.equals("Mocha s.equals("MochaJava")) Java")){{ ifif(inName inMochaJava==true; true; inMochaJava inName==false; false; }} inName elseifif(inPrice) (inPrice){{ else System.out.println("Theprice priceof ofMocha MochaJava Javais: is:""++s); s); System.out.println("The inMochaJava==false; false; inMochaJava inPrice==false; false; }} }} inPrice Start inName inMochaJava © Klaus Schild, 2003 19 Den Preis ausgeben publicvoid voidcharacters(char characters(char[][]buf, buf,int intoffset, offset,int intlen) len){{ public Stringss==new newString(buf, String(buf,offset, offset,len); len); String (inName&& &&s.equals("Mocha s.equals("MochaJava")) Java")){{ ifif(inName inMochaJava==true; true; inMochaJava inName==false; false; }} inName elseifif(inPrice) (inPrice){{ else System.out.println("Theprice priceof ofMocha MochaJava Javais: is:""++s); s); System.out.println("The inMochaJava==false; false; inMochaJava inPrice==false; false; }} }} inPrice Start inPrice inPrice © Klaus Schild, 2003 <priceList> <priceList> <coffee> <coffee> <name> <name> MochaJava Java Mocha </name> </name> <name> <name> MSJava Java MS </name> </name> <price> <price> 11.95 11.95 </price> </price> </coffee> </coffee> </priceList> </priceList> print(s) © Klaus Schild, 2003 21 Fehlerbehandlung 20 Start startElement = name? inName characters = Mocha Java? inMochaJava startElement = price? inPrice characters = s? print(s) © Klaus Schild, 2003 22 Fehlerbehandlung publicvoid voidstartElement(..., startElement(...,String StringelementName, elementName,...){ ...){ public (elementName.equals("name")){ inName inName==true; true; }} ifif(elementName.equals("name")){ elseifif(elementName.equals("price") (elementName.equals("price")&& &&inMochaJava inMochaJava){){ else inPrice==true; true; inPrice <name>MochaJava</name> Java</name> <name>Mocha inName==false; false; }}}} inName <name>MSJava</name> Java</name> <name>MS <price>11.95</price> <price>11.95</price> Kommt ein name-Element, wird der Zustand einfach nicht verändert. inName Kommt danach ein price-Element, wird der aktuelle Zustand inPrice. inMochaJava Dadurch wird der Preis von MS Java ausgegeben! © Klaus Schild, 2003 inMochaJava Fehlerbehandlung publicvoid voidstartElement(..., startElement(...,String StringelementName, elementName,...){ ...){ public (elementName.equals("name")){ inName inName==true; true; }} ifif(elementName.equals("name")){ elseifif(elementName.equals("price") (elementName.equals("price")&& &&inMochaJava inMochaJava){ ){ else inPrice==true; true; inPrice <name>Mocha Java</name> <name>Mocha Java</name> inName==false; false; }}}} inName <price>11.95</price> <price>11.95</price> inMochaJava erwartet price-Element inName Ein SAX-Parser überprüft immer die Wohlgeformtheit eines XML-Dokumentes. kann aber auch die Zulässigkeit bzgl. einer DTD oder eines Schema überprüfen Syntax- und Strukturfehler fängt bereits der SAX-Parser ab. Callback-Methoden können von einem wohlgeformten und zulässigen Dokument ausgehen. inPrice 23 © Klaus Schild, 2003 24 4 VorVor- und Nachteile von SAX Zusätzliche Schicht zum Datenzugriff Anwendung + sehr effizient, auch bei großen XML-Dateien – Kontext (Parse-Baum) muss von der Anwendung selbst verwaltet werden. SAX SAX – abstrahiert nicht von der spezifischen XML-Syntax startElement characters – nur Parsen von XML-Dokumenten möglich, keine Modifikation oder Erstellung von Dokumenten Datenzugriff Datenzugriff Anwendungslogik getPriceList() Immer Anwendungslogik durch spezielle Schicht von dem Datenzugriff trennen (nicht nur bei SAX). Z.B. könnte getPriceList() eine Liste von Ware-PreisPaaren liefern. sollte nicht nur von SAX-APIs, sondern auch von der XML-Syntax abstrahieren © Klaus Schild, 2003 25 © Klaus Schild, 2003 26 Document Object Model (DOM) XMLParser DOM-Parser DOM Anwendung W3C-Standard zum Zugreifen, Modifizieren und Erstellen von Parse-Bäumen nicht nur für XML-, sondern auch für HTML-Dokumente abstrakte Schnittstelle, unabhängig von Programmiersprachen im Ergebnis ein Einschritt-Pull-Parser © Klaus Schild, 2003 27 DOMDOM-ParseParse-Bäume <?xmlversion="1.0" version="1.0"?> ?> <?xml <priceList> <priceList> <coffee> <coffee> <name>MochaJava</name> Java</name> <name>Mocha <price>11.95</price> <price>11.95</price> </coffee> </coffee> </priceList> </priceList> © Klaus Schild, 2003 28 DOMDOM-ParseParse-Bäume Document Node <?xmlversion="1.0" version="1.0"?> ?> <?xml <priceList> <priceList> <coffee> <coffee> <name>MochaJava</name> Java</name> <name>Mocha <price>11.95</price> <price>11.95</price> </coffee> </coffee> </priceList> </priceList> NodeList Element Node: PriceList NodeList Element Node: coffee Beachte: Text-Inhalte werden als eigene Knoten dargestellt. Element Node: coffee NodeList Element Node: name Beachte: In DOM ist nicht priceList die Dokument-Wurzel. DOM führt virtuelle Dokument-Wurzel ein, um syntaktische Einheiten außerhalb von priceList (wie version="1.0") repräsentieren zu können. © Klaus Schild, 2003 29 © Klaus Schild, 2003 Element Node: price NodeList NodeList Text Node: Mocha Java Text Node: 11.95 30 5 Navigationsmodell Beispiel <priceList> <priceList> <coffee> <coffee> <name> <name> parentNode previousSibling Node MochaJava Java Mocha </name> </name> <price> <price> 11.95 11.95 </price> </price> </coffee> </coffee> </priceList> </priceList> nextSibling childNodes firstChild lastChild © Klaus Schild, 2003 31 Aufgabe: Gib des Preis von Mocha Java aus! Hierfür benötigen wir zwei Dinge: 1. einen DOM-Parser 2. eine passende Zugriffsmethode © Klaus Schild, 2003 32 Ein DOMDOM-Parser Zugriffsmethoden DocumentBuilderFactoryfactory factory== DocumentBuilderFactory.newInstance(); DocumentBuilderFactory.newInstance(); DocumentBuilderFactory DocumentBuilderbuilder builder==factory.newDocumentBuilder(); factory.newDocumentBuilder(); DocumentBuilder NodeListcoffeeNodes coffeeNodes==document.getElementsByTagName("coffee"); document.getElementsByTagName("coffee"); NodeList Documentdocument document==builder.parse("priceList.xml"); builder.parse("priceList.xml"); Document Direkter Zugriff auf bestimmte Elemente mit getElementsByTagName möglich. DocumentBuilderFactory.newInstance() liefert eine DocumentBuilderFactory. Die Methode newDocumentBuilder() von DocumentBuilderFactory liefert einen DOM-Parser. Resultat ist eine NodeList. <?xmlversion="1.0" version="1.0"?> ?> <?xml <priceList> <priceList> <coffee> <coffee> <name>MochaJava</name> Java</name> <name>Mocha <price>11.95</price> <price>11.95</price> </coffee> </coffee> </priceList> </priceList> Der DOM-Parser hat eine Methode parse(). © Klaus Schild, 2003 33 Zugriffsmethoden 34 Zugriffsmethoden NodeListcoffeeNodes coffeeNodes==document.getElementsByTagName("coffee"); document.getElementsByTagName("coffee"); NodeList for(int (inti=0; i=0;ii<<coffeeNodes.getLength(); coffeeNodes.getLength();i++) i++){{ for thisCoffeeNode==coffeeNodes.item(i); coffeeNodes.item(i); thisCoffeeNode <?xmlversion="1.0" version="1.0"?> ?> … <?xml … <priceList> <priceList> } } <coffee> <coffee> <name>MochaJava</name> Java</name> <name>Mocha <price>11.95</price> <price>11.95</price> </coffee> </coffee> </priceList> coffeeNodes.item(0) </priceList> © Klaus Schild, 2003 © Klaus Schild, 2003 35 NodeListcoffeeNodes coffeeNodes==document.getElementsByTagName("coffee"); document.getElementsByTagName("coffee"); NodeList for(int (inti=0; i=0;ii<<coffeeNodes.getLength(); coffeeNodes.getLength();i++) i++){{ for thisCoffeeNode==coffeeNodes.item(i); coffeeNodes.item(i); thisCoffeeNode NodethisNameNode thisNameNode==thisCoffeeNode.getFirstChild(); thisCoffeeNode.getFirstChild(); Node Stringdata data==thisNameNode.getFirstChild().getNodeValue(); thisNameNode.getFirstChild().getNodeValue(); String (data.equals("MochaJava")) Java")){{ ifif(data.equals("Mocha NodethisPriceNode thisPriceNode==thisCoffeeNode.getNextSibling(); thisCoffeeNode.getNextSibling(); Node <?xmlversion="1.0" version="1.0"?> ?> <?xml Stringprice price== thisPriceNode.getFirstChild().getNodeValue(); thisPriceNode.getFirstChild().getNodeValue(); String <priceList> <priceList> break;}}}} break; <coffee> <coffee> <name>MochaJava</name> Java</name> <name>Mocha firstChild <price>11.95</price> <price>11.95</price> </coffee> </coffee> </priceList> </priceList> © Klaus Schild, 2003 36 6 DOMDOM-Methoden DOMDOM-Methoden NodeListcoffeeNodes coffeeNodes==document.getElementsByTagName("coffee"); document.getElementsByTagName("coffee"); NodeList for(int (inti=0; i=0;ii<<coffeeNodes.getLength(); coffeeNodes.getLength();i++) i++){{ for NodeListcoffeeNodes coffeeNodes==document.getElementsByTagName("coffee"); document.getElementsByTagName("coffee"); NodeList for(int (inti=0; i=0;ii<<coffeeNodes.getLength(); coffeeNodes.getLength();i++) i++){{ for thisCoffeeNode==coffeeNodes.item(i); coffeeNodes.item(i); thisCoffeeNode NodethisNameNode thisNameNode==thisCoffeeNode.getFirstChild(); thisCoffeeNode.getFirstChild(); Node thisCoffeeNode==coffeeNodes.item(i); coffeeNodes.item(i); thisCoffeeNode NodethisNameNode thisNameNode==thisCoffeeNode.getFirstChild(); thisCoffeeNode.getFirstChild(); Node Stringdata data==thisNameNode.getFirstChild().getNodeValue(); thisNameNode.getFirstChild().getNodeValue(); String (data.equals("MochaJava")) Java")){{ ifif(data.equals("Mocha Stringdata data==thisNameNode.getFirstChild().getNodeValue(); thisNameNode.getFirstChild().getNodeValue(); String (data.equals("MochaJava")) Java")){{ ifif(data.equals("Mocha NodethisPriceNode thisPriceNode==thisCoffeeNode.getNextSibling(); thisCoffeeNode.getNextSibling(); Node <?xmlversion="1.0" version="1.0"?> ?> <?xml Stringprice price== thisPriceNode.getFirstChild().getNodeValue(); thisPriceNode.getFirstChild().getNodeValue(); String <priceList> <priceList> firstChild break; } } break; } } <coffee> <coffee> <name>MochaJava</name> Java</name> <name>Mocha Beachte: getFirstChild() liefert <price>11.95</price> <price>11.95</price> </coffee> den Text-Knoten, nicht dessen </coffee> </priceList> Inhalt „Mocha Java“! </priceList> © Klaus Schild, 2003 37 DOMDOM-Methoden © Klaus Schild, 2003 38 VorVor- und Nachteile von DOM <?xmlversion="1.0" version="1.0"?> ?> <?xml NodeListcoffeeNodes coffeeNodes==document.getElementsByTagName("coffee"); document.getElementsByTagName("coffee"); NodeList <priceList> <priceList> for (int i=0; i < coffeeNodes.getLength(); i++) { for (int i=0; i < coffeeNodes.getLength(); i++)<coffee> { <coffee> thisCoffeeNode==coffeeNodes.item(i); coffeeNodes.item(i); thisCoffeeNode <name>MochaJava</name> Java</name> <name>Mocha NodethisNameNode thisNameNode==thisCoffeeNode.getFirstChild(); thisCoffeeNode.getFirstChild(); <price>11.95</price> Node <price>11.95</price> </coffee> Stringdata data==thisNameNode.getFirstChild().getNodeValue(); thisNameNode.getFirstChild().getNodeValue(); </coffee> String firstChild </priceList> </priceList> if (data.equals("Mocha Java")) { if (data.equals("Mocha Java")) { NodethisPriceNode thisPriceNode==thisNameNode.getNextSibling(); thisNameNode.getNextSibling(); Node + Kontext (Parse-Baum) muss nicht von der Anwendung verwaltet werden. + direkter Zugriff auf Elemente und Attribute über ihre Namen (unabhängig von deren Position) möglich + Nicht nur Parsen von XML-Dokumenten möglich, sondern auch Modifikation und Erstellung von Dokumenten. Stringprice price== thisPriceNode.getFirstChild().getNodeValue(); thisPriceNode.getFirstChild().getNodeValue(); String break;}}}} break; © Klaus Schild, 2003 NodethisPriceNode thisPriceNode==thisNameNode.getNextSibling(); thisNameNode.getNextSibling(); Node Stringprice price== thisPriceNode.getFirstChild().getNodeValue(); thisPriceNode.getFirstChild().getNodeValue(); <?xmlversion="1.0" version="1.0"?> ?> String <?xml <priceList> break;}}}} <priceList> break; <coffee> <coffee> <name>MochaJava</name> Java</name> <name>Mocha nextSibling <price>11.95</price> <price>11.95</price> </coffee> </coffee> </priceList> </priceList> – speicherintensiv 39 © Klaus Schild, 2003 40 SAX oder DOM? SAX ist geeignet, um gezielt bestimmte Teile von XMLDokumenten herauszufiltern, ohne zu einem späteren Zeitpunkt andere Teile des Dokumentes zu benötigen. DOM ist geeignet, um auf unterschiedliche Teile eines XML-Dokumentes zu verschiedenen Zeitpunkten zuzugreifen. Schema-Übersetzer DOM ist zum Erstellen und Modifizieren von Dokumenten geeignet, SAX ist hierfür ungeeignet. © Klaus Schild, 2003 41 © Klaus Schild, 2003 42 7 Beispiel SchemaSchema-Übersetzer <priceList> <priceList> <coffee> <coffee> <name>MochaJava</name> Java</name> <name>Mocha <price>11.95</price> <price>11.95</price> </coffee> </coffee> </priceList> </priceList> Datenabstraktion XMLSchema Übersetzen Va Instanz XMLDokument lid ie re JavaKlassen Instanzen n JavaObjekte Î Java Architecture for XML Binding (JAXB) © Klaus Schild, 2003 43 Marshalling/ Marshalling/Unmarshalling Serialisieren © Klaus Schild, 2003 44 Warum sich noch mit XML beschäftigen? Mit Hilfe eines Schema-Übersetzers kann eine Anwendung vollständig von XML abstrahieren. marshal XMLDokument JAXB publicinterface interfacePriceList PriceList{{ public java.util.ListgetCoffee(); getCoffee(); java.util.List publicinterface interfaceCoffeeType CoffeeType{{ public StringgetName(); getName(); String voidsetName(String setName(Stringvalue) value) void java.math.BigDecimalgetPrice(); getPrice(); java.math.BigDecimal voidsetPrice(java.math.BigDecimal setPrice(java.math.BigDecimalvalue) value)}}}} void Deserialisieren Serialisieren PriceList-Schema Voraussetzung: XML-Schema oder eine DTD JavaObjekte Ein Anwendungsentwickler kann das XML-Schema in Java oder C# übersetzen und mit dem generierten Code XML-Dokumente lesen, modifizieren und erstellen. Deserialisieren unmarshal Serialisieren (marshalling) generiert aus Datenstrukturen der Anwendung ein XML-Dokument. to marshal = ordnen (Fakten), antreten lassen (Soldaten) Deserialisieren (unmarshalling) erstellt keinen ParseBaum, sondern Java-Objekte mit Methoden zum Zugreifen und Modifizieren der Daten. © Klaus Schild, 2003 45 Typisches EE-BusinessBusiness-Projekt Warumsollte solltesich sichalso alsoein einAnwendungsentwickler Anwendungsentwickler Warum überhauptnoch nochmit mitXML XMLoder oderXML-Schemata XML-Schemata überhaupt beschäftigen? beschäftigen? © Klaus Schild, 2003 46 Typisches EE-BusinessBusiness-Projekt: Phase I Welche Geschäftsdaten sollen ausgetauscht werden? Gibt es bereits einen passenden Branchenstandard (nicht unbedingt XML-basiert)? Zulieferer Wie sollen diese Geschäftsdaten in XML repräsentiert werden? Gibt es bereits einen geeigneten XML-Standard? Ziel: Branchenstandard in Form eines XML-Schemas Branchenvertreter wollen miteinander Geschäfte über das Internet machen. Software-Architektenentwickeln entwickeln Software-Architekten gemeinsameinen einen XML-basierten XML-basierten gemeinsam Branchenstandard(= (=XML-Schema). XML-Schema). Branchenstandard Sie müssen sich auf ein Austauschformat einigen. © Klaus Schild, 2003 47 © Klaus Schild, 2003 48 8 Typisches EE-BusinessBusiness-Projekt: Phase II Warum sich noch mit XML beschäftigen? Phase I: Software-Architekten beschäftigen sich intensiv mit entsprechender Branche, XML und XML-Schemata. XML Phase II: Programmierer können Schema-Übersetzer einsetzen und von XML abstrahieren. Branchenstandard liegt in Form eines XML-Schemas vor. Es gibt ein gemeinsames Verständnis der verwendeten XML-Syntax. Aufgabe: Realisierung der Schnittstelle zwischen betriebsinterner Software und dem XML-Standard. Programmiererkönnen könnenSchema-Übersetzer Schema-Übersetzereinsetzen einsetzen Programmierer undvon vonder derXML-Syntax XML-Syntaxabstrahieren. abstrahieren. und © Klaus Schild, 2003 49 © Klaus Schild, 2003 50 9