Überblick 1. XML Verarbeitung Verarbeitung von XML Dokumenten [2] © Robert Tolksdorf, Berlin Prof. Dr.-Ing. Robert Tolksdorf Freie Universität Berlin Institut für Informatik Netzbasierte Informationssysteme mailto: [email protected] http://www.robert-tolksdorf.de [1] © Robert Tolksdorf, Berlin Netzprogrammierung 11. XML Dokumente und ihre Verarbeitung Verarbeitung von XMLDokumenten [3] © Robert Tolksdorf, Berlin [Folien: Klaus Schild, NBI] © Klaus Schild, 2003 Lernziele Grundlegende Architektur • Was unterscheidet Pull- von Push-Parser? • Was unterscheidet Einschritt- von Mehrschritt-Parser? • Wie ordnen sich SAX und DOM bezüglich dieser Kategorien ein? Zeichenkette XMLDokument • Warum sollte immer die Anwendungslogik vom Datenzugriff getrennt werden? Anwendung Serialisierer Parser standardisierte APIs • Was sind Schema-Übersetzer? • Möglichst immer standardisierte APIs verwenden! • Parser: Analysiert XML-Dokument und erstellt Parse-Baum mit Tags, Text-Inhalten und Attribut-Wert-Paaren als Knoten. • Serialisierer: Generiert aus bestimmter Datenstruktur ein XMLDokument. © Klaus Schild, 2003 © Klaus Schild, 2003 Kategorien von Parser Pull-Parser • Pull- vs. Push-Parser: Wer hat die Kontrolle über das Parsen, die Anwendung oder der Parser selbst? • Einschritt- vs. Mehrschritt-Parser (engl. one-step vs. multistep parsing): Wird das XML-Dokument in einem Schritt vollständig geparst oder werden die einzelnen syntaktischen Einheiten Schritt für Schritt analysiert? • Beachte: Die Kategorien sind unabhängig voneinander, sie können beliebig kombiniert werden. © Klaus Schild, 2003 nächste Einheit? Pull-Parser geparste Einheit Anwendung • Die Anwendung hat die Kontrolle über das Parsen. • Die Analyse der nächsten syntaktischen Einheit muss von der Anwendung aktiv angefordert werden. • Beachte: „Pull” bezieht sich auf die Perspektive der Anwendung. © Klaus Schild, 2003 Push-Parser XML-Parser One-step geparste Einheit Push-Parser Multi-step JAXP Anwendung • Der Parser selbst hat die Kontrolle über das Parsen. DOM Pull Push SAX • Sobald der Parser eine syntaktische Einheit analysiert hat, benachrichtigt er die Anwendung und übergibt die entsprechende Analyse. • Beachte: „Push” bezieht sich wiederum auf die Perspektive der Anwendung. © Klaus Schild, 2003 JAXP: Java API for XML Processing • DOM: Document Object Model • SAX: Simple API for XML © Klaus Schild, 2003 Simple API for XML (SAX) • standardisiertes API für Mehrschritt-Push-Parsen von XML-Dokumenten SAX-Parser © Klaus Schild, 2003 • ursprünglich nur Java-API, inzwischen werden aber auch viele andere Sprachen unterstützt • kein W3C-Standard, sondern de facto Standard http://www.saxproject.org/ © Klaus Schild, 2003 Ereignisbasiertes Parsen mit SAX SAX-Parser Ereignis: neue syntaktische Einheit geparst Aufforderung zum Parsen Event Handler Anwendung 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> 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. • Sobald eine syntaktische Einheit geparst wurde, wird die Anwendung benachrichtigt (Ereignisfluss). • Beachte: Es wird kein Parse-Baum aufgebaut! © Klaus Schild, 2003 © Klaus Schild, 2003 Callback-Methoden Beispiel • startElement, endElement und characters werden Call-BackMethoden genannt, weil sie vom Parser aufgerufen werden. • Ein SAX-Parser hat für jede syntaktische Struktur in XML eine eigene Callback-Methode. • Die Standard-Implementierung der Call-Back-Methoden (DefaultHandler) tut jeweils nichts. • Die Standard-Implementierung einer Callback-Methode kann aber entsprechend den Erfordernissen überschrieben werden. © Klaus Schild, 2003 <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 Aufgabe: Gib des Preis von Mocha Java aus! Hierfür benötigen wir zwei Dinge: 1. einen SAX-Parser 2. passende CallbackMethoden Ein SAX-Parser Exkurs: Factory Method SAXParserFactoryfactory factory==SAXParserFactory.newInstance(); SAXParserFactory.newInstance(); SAXParserFactory SAXParsersaxParser saxParser==factory.newSAXParser(); factory.newSAXParser(); SAXParser Design Pattern aus „Design Patterns“ von Gamma, Helm, Johnson, Vlissides (1995) saxParser.parse("priceList.xml",handler); handler); saxParser.parse("priceList.xml", liefert ein Objekt • SAXParserFactory.newInstance() liefert eine SAXParserFactory. • Die Methode newSAXParser() liefert einen SAXParser mit einer Methode parse(). Objekt ist Instanz einer abstrakten Klasse oder einem Interface. wird von mehreren Klassen implementiert Beispiel: Iterator i = list.iterator(); • 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 © Klaus Schild, 2003 Die Callback-Methoden Die Callback-Methoden <priceList> <priceList> <coffee> <coffee> <name> <name> MochaJava Java Mocha </name> </name> <price> <price> 11.95 11.95 </price> </price> </coffee> </coffee> </priceList> </priceList> Aufgabe: Gib des Preis von Mocha Java aus! © Klaus Schild, 2003 Start startElement = name? inName characters = Mocha Java? inMochaJava startElement = price? inPrice characters = s? print(s) publicvoid voidstartElement(..., startElement(...,String StringelementName, elementName,...){ ...){ public if (elementName.equals("name")){ inName = true; if (elementName.equals("name")){ inName = true; }} elseifif(elementName.equals("price") (elementName.equals("price")&& &&inMochaJava inMochaJava){ ){ else inPrice==true; true; inPrice <name>MochaJava</name> Java</name> <name>Mocha inName = false; }}}} inName = false; <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 if (inName && s.equals("Mocha Java")) if (inName && s.equals("Mocha Java")) {{ inMochaJava==true; true; inMochaJava inName = false; inName = false; }} elseifif(inPrice) (inPrice){{ else System.out.println("The priceof ofMocha MochaJava Javais: is:""++s); s); System.out.println("The price inMochaJava = false; inMochaJava = false; inPrice==false; false; }} }} inPrice © Klaus Schild, 2003 Start inName Die Callback-Methoden Die Callback-Methoden publicvoid voidstartElement(..., startElement(...,String StringelementName, elementName,...){ ...){ public (elementName.equals("name")){ inName inName==true; true; }} ifif(elementName.equals("name")){ else if (elementName.equals("price") && inMochaJava ){ else if (elementName.equals("price") && inMochaJava ){ inPrice==true; true; inPrice <name>MochaJava</name> Java</name> <name>Mocha inName = false; }}}} inName = false; <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")){ else if (elementName.equals("price") && inMochaJava else if (elementName.equals("price") && inMochaJava ){){ inPrice==true; true; inPrice <name>MochaJava</name> Java</name> <name>Mocha inName = false; }}}} inName = false; <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 if (inName && s.equals("Mocha Java")){{ if (inName && s.equals("Mocha Java")) inMochaJava = true; inMochaJava = true; inName==false; false; }} inName else if (inPrice) else if (inPrice) {{ System.out.println("Theprice priceof ofMocha MochaJava Javais: is:""++s); s); System.out.println("The inMochaJava = false; inMochaJava = false; 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 if (inName && s.equals("Mocha Java")) if (inName && s.equals("Mocha Java")) {{ inMochaJava==true; true; inMochaJava inName==false; false; }} inName else if (inPrice) else if (inPrice) {{ System.out.println("Theprice priceof ofMocha MochaJava Javais: is:""++s); s); System.out.println("The inMochaJava = false; inMochaJava = false; inPrice==false; false; }} }} inPrice Start inName inMochaJava © Klaus Schild, 2003 © Klaus Schild, 2003 Die Callback-Methoden Fehlerbehandlung publicvoid voidstartElement(..., startElement(...,String StringelementName, elementName,...){ ...){ public if (elementName.equals("name")){ inName = true; if (elementName.equals("name")){ inName = true; }} elseifif(elementName.equals("price") (elementName.equals("price")&& &&inMochaJava inMochaJava){ ){ else inPrice==true; true; inPrice <name>MochaJava</name> Java</name> <name>Mocha inName = false; }}}} inName = false; <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 if (inName && s.equals("Mocha Java")) if (inName && s.equals("Mocha Java")) {{ inMochaJava==true; true; inMochaJava inName = false; inName = false; }} elseifif(inPrice) (inPrice){{ else System.out.println("The priceof ofMocha MochaJava Javais: is:""++s); s); System.out.println("The price inMochaJava = false; inMochaJava = false; inPrice==false; false; }} }} inPrice © Klaus Schild, 2003 Start inPrice <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> © Klaus Schild, 2003 inMochaJava inPrice Start startElement = name? inName characters = Mocha Java? inMochaJava startElement = price? inPrice characters = s? print(s) print(s) inName Fehlerbehandlung Fehlerbehandlung publicvoid voidstartElement(..., startElement(...,String StringelementName, elementName,...){ ...){ public (elementName.equals("name")){ inName inName==true; true; }} ifif(elementName.equals("name")){ else if (elementName.equals("price") && inMochaJava else if (elementName.equals("price") && inMochaJava ){){ inPrice==true; true; inPrice <name>MochaJava</name> Java</name> <name>Mocha inName = false; }}}} inName = false; <name>MSJava</name> Java</name> <name>MS <price>11.95</price> <price>11.95</price> inMochaJava erwartet price-Element Kommt ein name-Element, wird der Zustand einfach nicht verändert. Kommt danach ein price-Element, wird der aktuelle Zustand inPrice. Dadurch wird der Preis von MS Java ausgegeben! inName inMochaJava Ein SAX-Parser überprüft immer die Wohlgeformtheit eines XML-Dokumentes. Hat der SAX-Parser eine DTD oder ein Schema, kann er auch noch die Zulässigkeit des XML-Dokumentes ü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 © Klaus Schild, 2003 © Klaus Schild, 2003 Vor- 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. – Abstrahiert nicht von der spezifischen XML-Syntax – nur Parsen von XML-Dokumenten möglich, keine Modifikation oder Erstellung von Dokumenten SAX SAX startElement characters 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 © Klaus Schild, 2003 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 © Klaus Schild, 2003 Parse-Bäume Parse-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> Document Node NodeList Element Node: PriceList NodeList Element Node: coffee <?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> Beachte: In DOM ist nicht priceList die Dokument-Wurzel. DOM führt virtuelle Dokument-Wurzel ein, um auch syntaktische Einheiten außerhalb von priceList (wie version="1.0") repräsentieren zu können. © Klaus Schild, 2003 © Klaus Schild, 2003 Beachte: Text-Inhalte werden als eigene Knoten dargestellt. Element Node: coffee NodeList Element Node: name Element Node: price NodeList NodeList Text Node: Mocha Java Text Node: 11.95 Navigationsmodell Beispiel parentNode previousSibling Node nextSibling childNodes firstChild lastChild <priceList> <priceList> <coffee> <coffee> <name> <name> MochaJava Java Mocha </name> </name> <price> <price> 11.95 11.95 </price> </price> </coffee> </coffee> </priceList> </priceList> 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 © Klaus Schild, 2003 Ein DOM-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 DocumentBuilderFactory.newInstance() liefert eine DocumentBuilderFactory. Die Methode newDocumentBuilder() von DocumentBuilderFactory liefert einen DOM-Parser. Direkter Zugriff auf bestimmte Elemente mit getElementsByTagName möglich. Resultat ist eine NodeList. Der DOM-Parser hat eine Methode parse(). © Klaus Schild, 2003 © Klaus Schild, 2003 <?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> Zugriffsmethoden Zugriffsmethoden 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 … … thisCoffeeNode==coffeeNodes.item(i); coffeeNodes.item(i); thisCoffeeNode NodethisNameNode thisNameNode==thisCoffeeNode.getFirstChild(); thisCoffeeNode.getFirstChild(); Node }} coffeeNodes.item(0) <?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> 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 © Klaus Schild, 2003 DOM-Methoden DOM-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 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> © Klaus Schild, 2003 DOM-Methoden <?xmlversion="1.0" version="1.0"?> ?> <?xml NodeListcoffeeNodes coffeeNodes==document.getElementsByTagName("coffee"); document.getElementsByTagName("coffee"); NodeList <priceList> <priceList> for(int (inti=0; i=0;ii<<coffeeNodes.getLength(); coffeeNodes.getLength();i++) i++) for {{ <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> (data.equals("MochaJava")) Java")){{ ifif(data.equals("Mocha NodethisPriceNode thisPriceNode==thisNameNode.getNextSibling(); thisNameNode.getNextSibling(); Node Stringprice price== thisPriceNode.getFirstChild().getNodeValue(); thisPriceNode.getFirstChild().getNodeValue(); String break;}}}} break; Vor- und Nachteile von DOM + Kontext (Parse-Baum) muss nicht von der Anwendung verwaltet werden. + Auch 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. – speicherintensiv, insbesondere bei großen XML-Dateien © Klaus Schild, 2003 © Klaus Schild, 2003 SAX oder DOM? Typisches E-Business-Projekt • SAX ist geeignet, um gezielt bestimmte Teile von XMLDokumenten herauszufiltern, ohne dass zu einem späteren Zeitpunkt andere Teile des Dokumentes benötigt werden. Zulieferer • DOM ist geeignet, um auf unterschiedliche Teile eines XML-Dokumentes zu verschiedenen Zeitpunkten zuzugreifen. • DOM ist zum Erstellen und Modifizieren von Dokumenten geeignet, SAX ist hierfür ungeeignet. Branchenvertreter wollen miteinander Geschäfte über das Internet machen. Sie müssen sich auf ein Austauschformat einigen. © Klaus Schild, 2003 © Klaus Schild, 2003 Typisches E-Business-Projekt: Phase II Typisches E-Business-Projekt: Phase I • Welche Geschäftsdaten sollen ausgetauscht werden? XML • Gibt es bereits einen passenden Branchenstandard (nicht unbedingt XML-basiert)? • Wie sollen diese Geschäftsdaten in XML repräsentiert werden? Branchenstandard liegt in Form eines XML-Schemas vor. Es gibt ein gemeinsames Verständnis der verwendeten XML-Syntax. • Gibt es bereits einen geeigneten XML-Standard? • Es muss ein gemeinsames Verständnis der verwendeten XML-Syntax hergestellt werden. Aufgabe: Realisierung der Schnittstelle zwischen betriebsinterner Software und dem XML-Standard. Software-Architektenentwickeln entwickeln Software-Architekten gemeinsam einen XML-basierten gemeinsam einen XML-basierten Branchenstandard (=XML-Schema). XML-Schema). Branchenstandard (= Programmiererkönnen könnenSchema-Übersetzer Schema-Übersetzereinsetzen einsetzen Programmierer und von von der der XML-Syntax XML-Syntax abstrahieren. abstrahieren. und © Klaus Schild, 2003 © Klaus Schild, 2003 Hunter, David; Cagle, Kurt; Dix, Chris: Beginning XML XML Schemas, SOAP, XSLT, DOM, and SAX 2.0 2nd ed. 2001. Wrox Press 1-86100-559-8 Empfehlenswertes Skript einer anderen XMLVorlesung: http://www.jeckle.de/vorlesung/xml/ mehrere Interaktive XML-Kurse http://www.zvon.org • Phase I: Software-Architekten beschäftigen sich intensiv mit entsprechender Branche, XML und XML-Schemata. • Phase II: Programmierer können Schema-Übersetzer einsetzen und von XML abstrahieren. © Klaus Schild, 2003 [48] © Robert Tolksdorf, Berlin Literatur Warum sich noch mit XML beschäftigen?