Rozhraní pro práci s XML (SAX, DOM, pull) Obsah Základní pojmy ..........................................................................................................2 Cílem rozhraní je ................................................................................................................2 Hlavní typy rozhraní pro zpracování XML dat: .........................................................................2 Stromově orientovaná rozhraní (Tree-based API) ..............................................................2 Mapují XML dokument na stromovou strukturu v paměti ...........................................................2 Modely specifické pro konkrétní prostředí ...............................................................................2 Rozhraní založená na událostech (Event-based API) ..........................................................3 Při analýze ("parsing") dokumentu "vysílají" zpracovávající aplikaci sled událostí...........................3 Událostmi je např.: ..............................................................................................................3 SAX - příklad analýzy dokumentu..........................................................................................3 Kdy zvolit událostmi řízené rozhraní? .....................................................................................4 Vlastnosti (features) nastavitelné pro analýzu - parsing...............................................................4 SAX filtry..........................................................................................................................4 Další odkazy k SAX ............................................................................................................4 Rozhraní založená na technice "pull" ..............................................................................5 Rozhraní založená na technice "pull" ......................................................................................5 Streaming API for XML (StAX) ............................................................................................5 StAX - příklad s iterátorem ...................................................................................................5 StAX - příklad s kurzorem ....................................................................................................7 Document Object Model (DOM)....................................................................................8 Základní rozhraní pro tvorbu a přístup ke stromové reprezentaci XML dat.....................................8 Specifický DOM pro HTML dokumenty .................................................................................9 Odkazy k DOM ..................................................................................................................9 Implementace DOM ............................................................................................................9 Práce s DOM v Jávě ..................................................................................................10 Co potřebujeme?...............................................................................................................10 Co nejčastěji použijeme? ....................................................................................................10 Příklad 1 - vytvoření DOM stromu ze souboru........................................................................10 Příklad 2 - modifikace DOM stromu .....................................................................................11 Příklad 3 - uložení XML z DOM do souboru ..........................................................................11 Alternativní stromové modely k DOM ..........................................................................12 XML Object Model (XOM) ................................................................................................12 Alternativní parsery a stromové modely - NanoXML ...............................................................12 Prakticky dobře použitelný stromový model: dom4j .................................................................13 Kombinace stromových a událostmi řízených přístupů .....................................................13 Události -> strom ..............................................................................................................13 Strom -> události ..............................................................................................................13 Virtuální objektové modely .................................................................................................13 1 Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ Základní pojmy Cílem rozhraní je • poskytnout jednoduchý standardizovaný přistup ke XML datům "napojit" analyzátor (parser) na aplikaci a aplikace navzájem • odstínit aplikaci od fyzické struktury dokumentu (entity) • zefektivnit zpracování XML dat Hlavní typy rozhraní pro zpracování XML dat: Stromově orientovaná rozhraní (Tree-based API) • Rozhraní založená na událostech (Event-based API) • Rozhraní založená na "vytahování" událostí/prvků z dokumentu (Pull API) Stromově orientovaná rozhraní (Tree-based API) Mapují XML dokument na stromovou strukturu v paměti • dovolují libovolně procházet ("traverse") vzniklý strom; nejznámější je Document Object Model (DOM) konsorcia W3C, viz http://www.w3.org/DOM [http://www.w3 .org/DOM/] Modely specifické pro konkrétní prostředí • pro Javu: JDOM - http://jdom.org • pro Javu: dom4 jWlKIPFTJlA íli r priT r ik i. I-Binfc i [http://cs.wikipedia.org/wiki/Speci%C3%Alln%C3%AD:Search?search=dom4j] -http://dom4j.org • pro Javu: XOM - http://www.xom.nu • pro Python: 4Suite - http://4suite.org 2 Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ • pro PHP: SimpleXML - http://www.php.net/simplexml Rozhraní založená na událostech (Event-based API) Při analýze ("parsing") dokumentu "vysílají" zpracovávající aplikaci sled událostí. technicky realizováno jako volání metod ("callback") • aplikace poskytuje handlery, které volání zachytávají a zpracovávají • událostmi řízená rozhraní jsou "nižší úrovně" než stromová, protože • pro aplikaci zůstává "více práce" • jsou však úspornější na paměť (většinou i čas), samotná analýza totiž nevytváří žádné „trvalé" objekty Událostmi je napr.: • začátek a konec dokumentu (start document, end document) • začátek a konec elementu (start element, end element) - předá současně i atributy • instrukce pro zpracování (processing instruction) komentář (comment) • odkaz na entitu (entity reference) • Nejznámějším takovým rozhraním je SAX http://www.saxproject.org SAX - příklad analýzy dokumentu Hello, world!
vyprodukuje při analýze (parsingu) sled událostí: 3 Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ start document start element: doc {seznam atributů: prázdný} start element: para {seznam atributů: prázdný} characters: Hello, world! end element: para comment: that's all folks start element: hr end element: hr end element: doc end document Kdy zvolit událostmi řízené rozhraní? • O co snazší pro autora parseru, o to náročnější pro aplikačního programátora... • Aplikace si musí (někdy složitě) pamatovat stav analýzy, nemá nikdy "celý dokument pohromadě". Na úlohy, které lze řešit "lokálně", bez kontextu celého dokumentu, je to vhodné rozhraní. • Obvykle poskytuje nejrychlejší možné zpracování. • Aplikační nepříjemnosti lze obejít použitím nadstaveb, např. Streaming Transformations for XML (STX) [http://stx.sourceforge.net] Vlastnosti (features) nastavitelné pro analýzu - parsing Chování parseru produkujícího SAX události je možné ovlivnit nastavením tzv. features ^properties. Vlastnosti (features) nastavitelné pro analýzu (parsing) http://www.saxproject.org/?selected=get-set • Blíže k jednotlivým properties a features v článku Use properties and features in SAX parsers [???] (IBM DeveloperWorks/XML). SAX filtry SAX rozhraní nabízí možnost napsat třídu jako tzv. SAX filtr (přesněji implementaci rozhraní org.xml.sax.XMLFilter). Objekt takové třídy na jedné straně události přijímá, zpracuje je a posílá dále. Další informace k filtrování událostí naleznete např. v článku Change the events output by a SAX stream [http://www.ibm.com/developerworks/xml/library/x-tipsaxfilter/] (IBM DeveloperWorks/XML). Další odkazy k SAX 4 Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ "Přímo od zdroje" http://www.saxproject.org SAX Tutorial k JAXP - http://java.sun.com/webservices/docs/eal/tutorial/doc/JAXPSAX.html Rozhraní založená na technice "pull" Rozhraní založená na technice "pull" • Aplikace "nečeká na události", ale "vytahuje si" příslušná data ze vstupního parsovaného souboru. • Využíváme tam, kde "víme, co ve zdroji očekávat" a "postupně si to bereme" ... vlastně opak API řízeného událostmi. • Z hlediska aplikačního programátora velmi pohodlné, ale implementace bývají o něco pomalejší než klasická "push" událostmi řízená rozhraní. Pro Javu existuje XML-PULL parser API - viz Common API for XML Pull Parsing [http://www.xmlpull.org/] a také • nově vyvíjené rozhraní Streaming API for XML (StAX) [http://www.jcp.org/en/jsr/detail?id=173] vznikající "shora i zdola" jako produkt JCP (Java Community Process). Streaming API for XML (StAX) Toto API se později může stát standardní součástí javového prostředí pro práci s XML, tzv. JAXP. Nabízí dva přístupy k "pull" zpracování: • přístup k "vytahovaným" událostem prostřednictvím iterátoru - pohodlnější • nízkoúrovňový přístup přes tzv. kurzor - rychlejší StAX - příklad s iterátorem Příklad 1. StAX - přístup iterátorem import java.io.*; import java.util.Iterator; import j avax.xml.namespace.QName; import javax.xml.stream.*; import j avax.xml.stream.events.*; public class ParseByEvent { 5 Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ public static void main(String[] args) throws FileNotFoundException, XMLStreamException { // Use the reference implementation for the XML input factory System.setProperty("j avax.xml.stream.XMLInputFactory", "com.bea.xml.stream.MXParserFactory") ; // Create the XML input factory XMLInputFactory factory = XMLInputFactory.newlnstance() ; // Create the XML event reader FileReader reader = new FileReader("somefile.xml"); XMLEventReader r = factory.createXMLEventReader(reader); // Loop over XML input stream and process events while(r.hasNext()) { XMLEvent e = r.next(); processEvent(e); } } /** * Process a single XML event * Sparam e - the event to be processed */ private static void processEvent(XMLEvent e) { if (e.isStartElement()) { QName qname = ((StartElement) e).getName(); String namespaceURI = qname.getNamespaceURI(); String localName = qname.getLocalPart() ; Iterator iter = ((StartElement) e).getAttributes(); while (iter.hasNext()) { Attribute attr = (Attribute) iter.next(); QName attributeName = attr.getName(); String attributeValue = attr.getValue(); } } if (e.isEndElement()) { QName qname = ((EndElement) e).getName(); } if (e.isCharacters () ) { String text = ((Characters) e).getData(); } if (e.isStartDocument()) { String version = ((StartDocument) e).getVersion(); String encoding = ((StartDocument) e).getCharacterEncodingScheme(); boolean isStandAlone = ((StartDocument) e).isStandalone(); } } } 6 Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ Poznámka příklad převzat z Tip: Use XML streaming parsers [http://www.ibm.com/developerworks/xml/library/x-tipstx] (IBM DeveloperWorks, sekce XML). StAX - příklad s kurzorem Příklad 2. StAX - přístup kurzorem import java.io.*; import javax.xml.stream.*; public class ParseBylterator { public static void main(String[] args) throws FileNotFoundException, XMLStreamException { // Use reference implementation System.setProperty( "j avax.xml.stream.XMLInputFactory", "com.bea.xml.stream.MXParserFactory"); // Create an input factory XMLInputFactory xmlif = XMLInputFactory.newlnstance(); // Create an XML stream reader XMLStreamReader xmlr = xmlif.createXMLStreamReader(new FileReader("somefile.xml")); // Loop over XML input stream and process events while (xmlr.hasNext()) { processEvent(xmlr); xmlr.next(); } } /** * Process a single event * Sparam xmlr - the XML stream reader */ private static void processEvent(XMLStreamReader xmlr) { switch (xmlr.getEventType()) { case XMLStreamConstants.START_ELEMENT : processName(xmlr); processAttributes(xmlr); break; case XMLStreamConstants.END_ELEMENT : processName(xmlr); break; case XMLStreamConstants.SPACE : case XMLStreamConstants.CHARACTERS : 7 Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ int start = xmlr.getTextStart() ; int length = xmlr.getTextLength() ; String text = new String(xmlr.getTextCharacters() , start, length); break; case XMLStreamConstants.COMMENT : case XMLStreamConstants.PROCESSING_INSTRUCTION : if (xmlr.hasText()) { String piOrComment = xmlr.getText(); } break; } } private static void processName(XMLStreamReader xmlr) { if (xmlr.hasName()) { String prefix = xmlr.getPrefix() ; String uri = xmlr.getNamespaceURI() ; String localName = xmlr.getLocalName(); } } private static void processAttributes(XMLStreamReader xmlr) { for (int i = 0; i < xmlr.getAttributeCount(); i++) processAttribute(xmlr, i); } private static void processAttribute(XMLStreamReader xmlr, int index String prefix = xmlr.getAttributePrefix(index); String namespace = xmlr.getAttributeNamespace(index); String localName = xmlr.getAttributeName(index); String value = xmlr.getAttributeValue(index); } Poznámka příklad převzat z Tip: Use XML streaming parsers [http://www.ibm.com/developerworks/xml/library/x-tipstx] (IBM DeveloperWorks, sekce XML). Document Object Model (DOM) Základní rozhraní pro tvorbu a přístup ke stromové reprezentaci XML dat. Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ existují verze DOM Level 1, 2, 3 • DOM je obecně nezávislý na způsobu analýzy (parsingu) vstupního XML • Je popsán IDL definicemi+popisy rozhraní v jednotlivých jazycích (zejm. C++ a Java) Specifický DOM pro HTML dokumenty • Core (základ) DOM pro HTML je nyní "víceméně" sloučen s DOM pro XML • určen pro styly CSS • určen pro programování dynamického HTML (skriptování - VB Script, JavaScript) • kromě samotného dokumentu model zahrnuje i prostředí prohlížeče (např. windowWlKIPFDiA lil r p m- Fib i. L nib i [http://cs.wikipedia.org/wiki/Speci%C3%Alln%C3%AD:Search?search=window], history WlKIPFDlA [http://cs.wikipedia.org/wiki/Speci%C3%Alln%C3%AD:Search?search=history]...) Trip rni- Fil i. LniLi Odkazy k DOM • Tutoriál k JAXP, část věnovaná DOMPart III: XML and the Document Object Model (DOM) [http://java.sun.eom/xml/jaxp/dist/l. 1/docs/tutorial/dom/index.html] • Portál věnovaný DOM http://www.oasis-open.org/cover/dom.html Vizuální přehled DOM 1 rozhraní http://www.xml.eom/pub/a/1999/07/dom/index.html • Tutoriál "Understanding DOM (Level 2)" na http://ibm.eom/developer/xmlhttp://ibm.com/developer/xml [http://ibm.com/developer/xml] Implementace DOM • v mnoha parserech, např. Xerces [http://xml.apache.org] • jako součást JAXP (Java API for XML Processing) - http://java.sun.com/xml/jaxp/index.html • i jako samostatné, nezávislé na parserech: např. dom4 j WlKIPFillA íli r p n t Pik i. unikl [http ://cs. wikipedia. org/wiki/Speci%C3 %A 1 ln%C3 %AD: Search? search=dom4j ] http://dom4j.org • EXMLWUCIPFMA íli p p pit Fík i. ĽBini i 9 Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ [http://cs.wikipedia.org/wiki/Speci%C3%Alln%C3%AD:Search?search=EXML] (Electric XML) - http://www.themindelectric.net Práce s DOM v Jávě Co potřebujeme? Ve všech novějších verzích Javy (JDK i JRE) je podpora DOM zabudována ve standardních knihovnách, nemusíme tedy nic doinstalovávat. V programech musíme nicméně importovat potřebné symboly (rozhraní, příp. třídy), většinou z balíku org . w3c . dom. Co nejčastěji použijeme? Nejčastěji používanými rozhraními jsou: Element odpovídá pojmu "element" v logické struktuře dokumentu; zpřístupňuje název elementu, atributy, dceřinné uzly (vč. textových). Zajímavé metody: Node getParentNode () - vrátí rodičovský uzel String getTextContent () - vrátí textový obsah elementu NodeList getElementsByTagName (String name) - vrátí seznam následníků (dceřinných uzlů a jejich následníků) majících dané jméno Node nadrozhraní Elementu, odpovídá obecnému uzlu v logické struktuře, tzn. může to být jak element, textový uzel, komentář, atd. NodeList jakýsi seznam uzlů (např. získatelný voláním getElementsByTagName), lze s ním pracovat metodami: int getLength () - vrátí počet uzlů v seznamu Node item (int index) -vrátí uzel na dané pozici index Document odpovídá uzlu dokumentu (je to rodič kořenového elementu) Příklad 1 - vytvoření DOM stromu ze souboru Příklad metody, která načte DOM strom z XML souboru (viz Úloha 1): /** * Konstruktor, který vytvori novou instanci tridy Ulohal * nactenim obsahu xml dokumentu se zadaným URL. 10 Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ */ private Ulohal(URL url) throws SAXException, ParserConfigurationException, IOException { // Vytvorime instand továrni tridy DocumentBuilderFactory factory = DocumentBuilderFactory.newlnstance(); // Pomoci továrni tridy ziskame instand DocumentBuilderu DocumentBuilder builder = factory.newDocumentBuilder(); // DocumentBuilder použijeme pro zpracováni XML dokumentu // a ziskame model dokumentu ve formátu W3C DOM doc = builder.parse(url.toString()); } Příklad 2 - modifikace DOM stromu Přiklad metody manipulující (modifikující) DOM strom dokumentu (viz Úloha 1): * Metoda na úpravu platu. * Ma-li osoba menši plat nez minimum, * bude ji plat zvysen na minimum. * S ostatnimi osobami se nic nedeje. */ public void adjustSalary(double minimum) { // ziskej seznam elementů s platy NodeList salaries = doc.getElementsByTagName("salary"); for (int i = 0; i < salaries.getLength(); i++) { // ziskej element s platem Element salaryElement = (Element) salaries.item(i); // ziskej plat double salary = Double.parseDouble(salaryElement.getTextContent()); if (salary < minimum) { // modifikuj textový uzel/obsah elementu salaryElement.setTextContent(String.valueOf(minimum)); } } } Příklad 3 - uložení XML z DOM do souboru n Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ Přiklad metody ukládající DOM strom do souboru (viz Úloha 1). Postup používá transformace, které zatím neumíme. Berme to tedy jako "černou skříňku" :-) public void serializetoXML(File output) throws lOException, TransformerConfigurationException, TransformerException // Vytvorime instanci továrni tridy TransformerFactory factory = TransformerFactory.newlnstance(); // Pomoci továrni tridy ziskame instanci tzv. kopirovaciho transformeru Transformer transformer = factory.newTransformer(); // Vstupem transformace bude dokument v paměti DOMSource source = new DOMSource(doc); // Výstupem transformace bude vystupni soubor StreamResult result = new StreamResult(output); // Provedeme transformaci transformer.transform(source, result); } Alternativní stromové modely k DOM XML Object Model (XOM) XOM {XML Object Model) vznikl jako one-man-projekt (autor Elliote Rusty Harold). • Jde o rozhraní, které je "papežštější než papež" a striktně respektuje logický model XML dat. • Motivaci a specifikaci najdete na domovské stránce XOM [http://cafeconleche.org/XOM/]. Tam je též k získání open-source implementace XOM [http://cafeconleche.org/XOM/xom-l.0d24.zip] a • dokumentace API [http://cafeconleche.org/XOM/apidocs/]. Alternativní parsery a stromové modely - NanoXML • velmi malé (co do velikosti kódu) stromové rozhraní a parser v jednom • dostupné jako open-source na http://nanoxml.n3 .net • adaptované též pro mobilní zařízení 12 Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ • z hlediska rychlosti a paměťové efektivity za běhu ale nejlepší není Prakticky dobře použitelný stromový model: dom4j pohodlné, rychlé a pamětově efektivní stromově-orientované rozhraní • psané pro Javu, optimalizované pro Javu... • dostupné jako open-source na http://dom4j .org • nabízí perfektní přehled díky "kuchařce" [http://dom4j.org/cookbook/cookbook.html] • dom4j je výkonný, viz srovnání efektivity jednotlivých stromových modelů [http://www.ibm.com/developerworks/xml/library/x-injava/] Kombinace stromových a událostmi řízených přístupů Události -> strom • Je např. možné "nezajímavou" část dokumentu přeskočit nebo odfiltrovat pomocí sledování událostí a pak • za "zajímavé" části vytvořit strom v paměti a ten zpracovávat. Strom -> události • Vytvoříme strom dokumentu (a zpracujeme ho) a strom následně procházíme a generujeme události jako bychom četli výchozí soubor. • Toto umožňuje snadnou integraci obou typů zpracování v jedné aplikaci Virtuální objektové modely • DOM model dokumentu není přítomen v paměti, je zprostředkováván "on demand" při přístupu k jednotlivým uzlům spojuje výhody událostmi řízeného a stromového modelu zpracování (rychlost + komfort) 13 Rozhraní pro práci s XML (SAX, _________DOM, pull)_________ Wl KIPFDIA [http://cs.wikipedia.org/wiki/Speci%C3%A11n%C3%AD: Search?search=Sablotron] "Tlir Fn-i- Fib i.LbviLi (např. viz http://www.xml.eom/pub/a/2002/03/13/sablotron.html nebo http://www.gingerall.org/charlie/ga/xml/p_sab.xml) 14