500 likes | 607 Views
SAX & DOM. Laurea Magistrale in Informatica Reti 2 (2005/06). dott. Francesco De Angelis francesco.deangelis@unicam.it. Agenda. Introduzione e confronto approcci SAX DOM. Introduzione e confronto approcci. Applicazione. XML parser. XSD. DTD. XML. Il parser.
E N D
SAX & DOM Laurea Magistrale in Informatica Reti 2 (2005/06) dott. Francesco De Angelis francesco.deangelis@unicam.it
Agenda • Introduzione e confronto approcci • SAX • DOM SAX & DOM
Applicazione XML parser XSD DTD XML Il parser • Il parser si occupa di: • Recuperare il documento XML • Caricare i dati in memoria • Presentare all’applicazione un’interfaccia di alto livello • (opzionalmente) fornire servizi di validazione • (opzionalmente) fornire servizi di ricerca SAX & DOM
Applicazione nome libro autore … <libro titolo=“Corso diXML“> <autore> <nome>Francesco</nome> <cognome>De Angelis</cognome> </autore> <autore> <nome>Alberto</nome> <cognome>Polzonetti</cognome> </autore> <capitolo titolo=“SAX and DOM">...</capitolo> </libro> XML Parser Approccio ad eventi • Il parser scandisce l’intero file • Per ogni elemento informa l’applicazione tramitela tecnica del callback t SAX & DOM
attr libro titolo=“…” Applicazione autore nome <libro titolo=“Corso di XML“> <autore> <nome>Francesco</nome> <cognome>De Angelis</cognome> </autore> <autore> <nome>Alberto</nome> <cognome>Polzonetti</cognome> </autore> <capitolo titolo=“SAX and DOM">...</capitolo> </libro> cognome XML Parser Approccio del modello • Il parser costruisce una struttura ad albero che rappresenta il documento • Fornisce all’applicazione delle API per navigarel’albero SAX & DOM
Confronto tra gli approcci SAX & DOM
JAXP • Java API for XML Processing (JAXP) • Supporto standard di SUN per l’elaborazione di XML • Propone due standard per le due impostazioni: • SAX (Simple API for XML) ad eventi • DOM (Document Object Model) basato su una rappresentazione astratta in memoria SAX & DOM
SAX e DOM • Anche se si ritenesse DOM come la scelta migliore per la propria applicazione Java, capire SAX è importante per vari motivi: • Il sistema di gestione degli errori del DOM è “ereditato” da SAX • Essendo SAX la prima API XML per Java, resta alla base anche dell’implementazione DOM • Le librerie Java usano SAX per leggere un file XML e creare il DOM corrispondente! SAX & DOM
Introduzione a SAX • SAX, o Simple API for XML, in origine è stata sviluppata come API per accedere ad XML con Java. • La homepage del progetto SAX (SourceForge) è http://www.saxproject.org/ • Basa il suo sistema di parsing sugli eventi • Inizio di un documento • Apertura e chiusura di un elemento • Apertura e chiusura di un blocco caratteri • Ingresso ed uscita dallo scope di un namespace • Caratteri, Process Instruction • Fine del documento SAX & DOM
Utilità e Limiti di SAX • Il parser SAXnon costruisce documenti XML, né conserva alcuna struttura in memoria alla fine del parsing. • Se il programmatore vuole operare sul documento letto, dovrà scrivere manualmente tutto il codice, basandosi sui dati passati con gli eventi SAX. • In generale SAX necessita di molto più codice di DOM, ma è molto più leggero. • Il programmatore può implementare solo quello che è strettamente utile, e non è necessario allocare il documento in memoria. SAX & DOM
Gestire gli Eventi SAX • Per ricevere le notifiche dal parser SAX, il codice deve registrare nel parser una classe org.xml.sax.DefaultHandlerche implementa l’interfacciaorg.xml.sax.ContentHandler • I vari metodi di questa interfaccia ricevono tutte le informazioni necessarie per trattare gli eventi. • Ad esempio, il metodo startElement riceve il nome dell’elemento e del suo namespace, nonché la lista degli attributi associati. SAX & DOM
L’handler di SAX Interface ContentHandler { void setDocumentLocator(Locator locator); void startDocument(); void startElement(String namespaceURI,String localName, String qName, Attributes atts); void startPrefixMapping(String prefix, String uri); void characters(char[] ch, int start, int length); void endDocument(); void endElement(String namespaceURI,String localName, String qName); void endPrefixMapping(String prefix); void ignorableWhitespace(char[] ch, int start, int length); void processingInstruction(String target, String data); void skippedEntity(String name); } SAX & DOM
L’handler di SAX • La classe DefaultHandler implementa l’interfaccia permettendo all’applicazione di ridefinire (override) solo i metodi desiderati public class MyHandler extends DefaultHandler { public void startElement(String namespaceURI, String localName, String qualifiedName, Attributes att) throws SAXException { System.out.println("startElement: " + qualifiedName); } public void characters(char ch[], int start, int length) throws SAXException { System.out.println("characters " + start + " to " + (start + length - 1) + ": " + new String(ch, start, length)); } public void endElement(String namespaceURI, String localName, String qualifiedName) throws SAXException { System.out.println(“endElement: /" + qualifiedName); } } SAX & DOM
Utilizzo dell’handler SAX • Il client utilizza la classe di Factory per recuperare il parser • Al parser viene chiesto di “parsare” il file come un processo autonomo public class SimpleSax { public static void main(String[] args) { SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setValidating(true); SAXParser sxp; sxp = factory.newSAXParser(); DefaultHandler handler = new SimpleHandler(); sxp.parse(new File("xml/articolo.xml").getAbsolutePath(),handler); } } SAX & DOM
Gestire gli Errori SAX • Gli errori generati dal parser SAX sono incapsulati in eccezioni che però non vengono mai sollevate. • Invece, le eccezioni vengono passate a un oggetto con interfaccia ErrorHandler registrato nel parser. • Se nessun oggetto di questo tipo viene specificato dal programmatore, gli errori di parsing non vengono segnalati! • Anche il DOM usa questo modello di errore! SAX & DOM
ErrorHandler Interface ErrorHandler { void error(SAXParseException exception) void fatalError(SAXParseException exception) void warning(SAXParseException exception) } Class SAXParseException { intgetColumnNumber() intgetLineNumber() StringgetPublicId() StringgetSystemId() } • La classe org.xml.sax.helpers.DefaultHandler fornisce una implementazione di default per ErrorHandler e altre interfacce utili per SAX • E’ possibile estendere questa classe per implementare più facilmente il proprio ErrorHandler SAX & DOM
SAX con JAXP import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.SAXParser; import org.xml.sax.helpers.DefaultHandler; SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setValidating(true); try { SAXParser sxp = factory.newSAXParser(); } catch (javax.xml.parsers.ParserConfigurationException) { } DefaultHandler handler = new DefaultHandler(); try { sxp.parse(filename,handler); } catch (java.io.IOException ioe) { } catch (org.xml.sax.SAXParseException spe) { } catch (org.xml.sax.SAXException se) { } SAX & DOM
SAX con Xerces import org.apache.xerces.parsers.SAXParser; import org.xml.sax.helpers.DefaultHandler; SAXParser sxp = new SAXParser(); try { sxp.setFeature( "http://xml.org/sax/features/validation", true ); } catch (org.xml.sax.SAXNotRecognizedException ex ) { } catch (org.xml.sax.SAXNotSupportedException ex ) { } DefaultHandler handler = new DefaultHandler(); sxp.setContentHandler(handler); sxp.setErrorHandler(handler); try { sxp.parse(filename); } catch (java.io.IOException ioe) { } catch (org.xml.sax.SAXParseException spe) { } catch (org.xml.sax.SAXException se) { } SAX & DOM
Definizione di DOM • E’ un’API (Application Programming Interface) per documenti XML • Il DOM definisce una modalità di rappresentazione dei documenti XML accessibile da un linguaggio di programmazione, e le operazioni per la loro manipolazione SAX & DOM
Definizione di DOM • Definisce le operazioni necessarie per operare sulla rappresentazione intermedia • Parsing di un file = caricamento della struttura • Costruzione di un nuovo documento • Browsing e navigazione • Aggiungere, eliminare, modificare e spostare le componenti • Specifica le operazioni indipendentemente dal linguaggio, esistono implementazioni di DOM in linguaggi differenti: • Linguaggi server-side : java, C++, C# • Linguaggi di script: VB-Script, JavaScript SAX & DOM
I livelli di DOM • Livello 0 : • Funzionalità originali di Netscape / IE • NON è una raccomandazione W3C • Livello 1 – Settembre 2000: • Oggetti fondamentali per il modello DOM • navigazione di un documento DOM e manipolazione del contenuto. • Non completamente compatibile con il livello 0 • Livello 2 – Novembre 2000: • Namespace e validazione • modello ad eventi per il controllo • Livello 3 - Working Draft Febbraio 2004 • ... La specifica attuale è al Livello 2, tuttavia alcune specifiche del Livello 3 sono già raccomandazioni del W3C. SAX & DOM
La struttura di DOM • DOM vede i documenti come una struttura gerarchica ad albero, composta da oggetti di tipo Node • Ogni nodo può avere uno o più figli • In realtà, la struttura è una “foresta” perché può anche contenere più alberi distinti. • Tuttavia, l’utente che accede al documento tramite l’interfaccia DOM, lo vedrà effettivamente come un albero. • Il DOM definisce solo la vista logica: non specifica come debbano essere effettivamente strutturati in memoria. SAX & DOM
I modelli a oggetti • Il DOM, come modello ad oggetti, definisce: • Gli oggetti usati per rappresentare e manipolare un documento XML. • Le interfacce usate per interagire con gli oggetti definiti. • La semantica richiesta dagli oggetti e dalle interfacce definite. • Le relazioni e interazioni tra le interfacce e gli oggetti definiti. SAX & DOM
La vista del DOM su XML document <song> track=9 <artist> <title> <comment> <length> <name> Corazon Espinado <minutes> <seconds> <songtrack="9"> <artist> <name>Santana</name> </artist> <title>Corazon Espinado</title> <comment>First Hit from the Album</comment> <length> <minutes>4</minutes> <seconds>36</seconds> </length> </song> Santana 4 36 First Hit from the Album SAX & DOM
Caricamento di un DOM import org.w3c.dom.*; import javax.xml.parsers.*; import org.xml.sax.*; Definizione DOM standard Implementazione di JAXP DOM usa SAX DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse("libro.xml"); • Il DOM di JAXP è definito nel package org.w3c.dom • Fornisce un’interfaccia standard che si appoggia su implementazioni differenti • Sono disponibili implementazioni differenti (SUN, Apache, Oracle) • L’implementazione di SUN è in javax.xml.parsers SAX & DOM
Navigazione di un DOM • Estrazione del nodo radice e stampa del nome del nodo • Nodi figli • Attributi Element root = doc.getDocumentElement(); System.out.println(root.getNodeName()); NodeList children = root.getChildNodes(); for (int i = 0; i < children.getLength(); i++) System.out.println(children.item(i).getNodeName); NamedNodeMap map = root.getAttributes(); for (int i = 0; i < map.getLength(); i++) System.out.println(map.item(i).getNodeName()); SAX & DOM
Tipizzazione • Tipizzazione tramite attributi di descrizione n.getNodeType() == n.ELEMENT_NODE SAX & DOM
Validazione e Namespace • Per default DOM è non validante • Una volta abilitata la validazione, questa avviene tramite il DTD • Tuttavia è possibile utilizzare XSD associando il corrispettivo namespace alla proprietà “http://java.sun.com/xml/jaxp/properties/schemaLanguage” • In maniera analoga è possibile abilitare la gestione dei namespace factory.setValidating(true); factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema"); factory.setNamespaceAware(true); SAX & DOM
Error Handling • Eredita la gestione degli errori di SAX • l’applicazione si “registra” come listener per li eventi che segnalano un errore • Tre tipi di errori: fatali, errori semplici, warning class Handler implements ErrorHandler { public void fatalError(SAXParseException ex) throws SAXException { ex.printStackTrace(); } public void error(SAXParseException ex) throws SAXParseException { ex.printStackTrace(); throw ex; } public void warning(SAXParseException err) throws SAXParseException { System.out.println("** Warning" + err.getLineNumber() + err.getMessage()); } } builder.setErrorHandler(new Handler()); SAX & DOM
Browsing e stampa public static void print(Node n, String spaces) { if (n == null) return; if (n instanceof Element) { String s = spaces + n.getNodeName() + " ("; NamedNodeMap map = n.getAttributes(); if (map != null) for (int i = 0; i < map.getLength(); i++) s += map.item(i).getNodeName() + "=" + map.item(i).getNodeValue(); s += ")"; System.out.println(s); } else if (n instanceof Text) System.out.println(spaces + n.getNodeValue()); NodeList children = n.getChildNodes(); for (int i = 0; i < children.getLength(); i++) print(children.item(i), spaces + “ – “); } Element root = doc.getDocumentElement(); print(root, “”); SAX & DOM
Esempio • XML in ingresso <?xml version="1.0" encoding="ISO-8859-1"?> <libro titolo=“Corso di XML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.elet.polimi.it" xsi:schemaLocation="http://www.elet.polimi.it libro4b.xsd"> <autore> <nome>Francesco</nome> <cognome>De Angelis</cognome> </autore> <autore> <nome>Alberto</nome> <cognome>Polzonetti</cognome> </autore> <capitolo titolo=“SAX and DOM">...</capitolo> </libro> SAX & DOM
Esempio • Output libro ( titolo=Corso di XML xmlns=http://www.elet.polimi.it xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation=http://www.elet.polimi.it libro3b.xsd) - autore () - - nome () - - - Francesco - - cognome () - - - De Angelis - autore () - - nome () - - - Alberto - - cognome () - - - Polzonetti - capitolo ( titolo=SAX and DOM) - - ... SAX & DOM
Creazione del nodo Element root = doc.getDocumentElement(); Element cap = doc.createElement("capitolo"); cap.setAttribute("titolo", "Introduzione"); cap.appendChild(doc.createTextNode("... testo ...")); Node capitolo = doc.getElementsByTagNameNS("http://www.elet.polimi.it", "capitolo").item(0); root.insertBefore(cap, capitolo); doc.normalize(); Creazione dell’attributo Ricerca del primo capitolo presente Inserimento normalizzazione. Es: unisce nodi di testo consecutivi Modifica dell’albero • DOM permette di inserire nuovi elementi nell’albero SAX & DOM
Gli oggetti Node: la base del DOM • Il DOM presenta i documenti come una struttura gerarchica di oggetti di tipo Node. • Ciascun oggetto nel documento in realtà implementa una interfaccia più specifica per il suo tipo, che è sempre derivata da Node • I Node possono avere zero o più nodi figli • L’interfaccia di Node include le operazioni di base eseguibili su ogni tipo di oggetto (indipendentemente dal suo tipo specifico) in un documento XML SAX & DOM
Tipi di Nodo (nodeType) • I tipi specifici per i nodi sono identificati dalle costanti dell’interfaccia Node: • ELEMENT_NODE: il nodo è un elemento (= 1) • ATTRIBUTE_NODE: il nodo è un attributo (= 2) • TEXT_NODE: il nodo è del testo (= 3) • CDATA_SECTION_NODE: il nodo è una sezione CDATA (= 4) • ENTITY_REFERENCE_NODE: il nodo è un riferimento ad entità (= 5) • ENTITY_NODE: il nodo è un’entità (= 6) • PROCESSING_INSTRUCTION_NODE: il nodo è una PI (= 7) • COMMENT_NODE: il nodo è un commento (= 8) • DOCUMENT_NODE: il nodo è un documento (non la radice!) (= 9) • DOCUMENT_TYPE_NODE: il nodo è un DOCTYPE (= 10) • DOCUMENT_FRAGMENT_NODE: il nodo è un frammento (= 11) • NOTATION_NODE: il nodo è una NOTATION (= 12) SAX & DOM
Interfaccia degli oggetti Node interface Node { const unsigned short ELEMENT_NODE = 1; //…ed altre costanti di tipo... readonly attribute DOMString nodeName; attribute DOMString nodeValue; readonly attribute unsigned short nodeType; readonly attribute Node parentNode; readonly attribute NodeList childNodes; readonly attribute Node firstChild; readonly attribute Node lastChild; readonly attribute Node previousSibling; readonly attribute Node nextSibling; readonly attribute NamedNodeMap attributes; readonly attribute Document ownerDocument; Node insertBefore(in Node newChild,in Node refChild) raises(DOMException); Node replaceChild(in Node newChild, in Node oldChild) raises(DOMException); Node removeChild(in Node oldChild) raises(DOMException); Node appendChild(in Node newChild) raises(DOMException); boolean hasChildNodes(); Node cloneNode(in boolean deep); }; SAX & DOM
Semantica dei Metodi di Node • Le funzioni di Node per la manipolazione dei nodi figli sono • appendChild, • removeChild, • replaceChild, • insertBefore. • La legalità di ciascuno di questi metodi dipende dal tipo effettivo del nodo. • Nel caso l’operazione non sia disponibile (ad esempio, appendChild su un nodo Text), viene generata un’eccezione di tipo DOMException. SAX & DOM
Interfaccia Element interface Element { readonly attribute DOMString tagName; DOMString getAttribute(in DOMString name); void setAttribute(in DOMString name, in DOMString value) raises(DOMException); void removeAttribute(in DOMString name) raises(DOMException); Attr getAttributeNode(in DOMString name); Attr setAttributeNode(in Attr newAttr) raises(DOMException); Attr removeAttributeNode(in Attr oldAttr) raises(DOMException); NodeList getElementsByTagName(in DOMString name); void normalize(); }; • Il metodo getElementsByTagName restituisce i soli figli del nodo che siano elementi con uno specifico nome (filtra cioè i childNodes). • Il metodo normalize serve a fondere nodi Text adiacenti nel sottoalbero controllato dall’elemento. SAX & DOM
Interfaccia Attr interface Attr { readonly attribute DOMString name; readonly attribute boolean specified; attribute DOMString value; }; • I valori per name e value sono accessibili anche attraverso i metodi getName e getValue dell’interfaccia Node • L’attributo specified è false se l’attributo non era presente nel documento, ma è stato inserito dal parser con il suo valore di default specificato nel DTD associato al documento stesso. In caso contrario, l’attributo è true SAX & DOM
NodeList e NamedNodeMap interface NodeList { Node item(in unsigned long index); readonly attribute unsigned long length; }; interface NamedNodeMap { Node getNamedItem(in DOMString name); Node setNamedItem(in Node arg, in DOMString value) raises(DOMException); Node removeNamedItem(in DOMString name) raises(DOMException); Node item(in unsigned long index); readonly attribute unsigned long length; }; • Le liste vengono restituite da vari metodi del DOM. • La NamedNodeMap contiene elementi accessibili, oltre che per indice (come in NodeList), anche attraverso il nome (l’attributo nodeName di Node). SAX & DOM
Interfaccia Document interface Document { readonly attribute DocumentType doctype; readonly attribute DOMImplementation implementation; readonly attribute Element documentElement; Element createElement(in DOMString tagName) raises(DOMException); DocumentFragment createDocumentFragment(); Text createTextNode(in DOMString data); Comment createComment(in DOMString data); CDATASection createCDATASection(in DOMString data) raises(DOMException); ProcessingInstruction createProcessingInstruction(in DOMString target, in DOMString data) raises(DOMException); Attr createAttribute(in DOMString name) raises(DOMException); EntityReference createEntityReference(in DOMString name) raises(DOMException); NodeList getElementsByTagName(in DOMString tagname); }; • L’oggetto Document fornisce i metodi per creare i nodi che compongono il documento XML! • documentElement rappresenta l’elemento radice del documento. SAX & DOM
Il DOM con Java: JAXP • JAXP è un’API generica offerta da Java per manipolare il DOM. • In realtà, JAXP è un’interfaccia astratta che deve poggiarsi su una vera implementazione del DOM fornita da terze parti. • E’ possibile usare anche direttamente l’implementazione del DOM. • Noi faremo riferimento al pacchetto Xerces dell’Apache XML Project, di gran lunga il più diffuso e perfezionato. SAX & DOM
DOM con JAXP • JAXP è contenuta nel namespace javax.xml.parsers e javax.xml.transformer import org.w3c.dom.Document; import org.w3c.dom.Element; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder builder = factory.newDocumentBuilder(); } catch (javax.xml.parsers.ParserConfigurationException) { } Document doc = builder.newDocument(); Element root = doc.CreateElement(“HTML”); Element body = doc.CreateElement(“Body”); body.setAttribute(“bgcolor”,”red”); root.appendChild(body); doc.appendChild(root); SAX & DOM
Parsing XML con JAXP • Il controllo offerto dalle interfacce generiche JAXP è minore. import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import org.w3c.dom.Document; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); factory.setNamespaceAware(true); try { DocumentBuilder builder = factory.newDocumentBuilder(); } catch (javax.xml.parsers.ParserConfigurationException) { } try { Document doc = builder.parse(filename); } catch (java.io.IOException ioe) { } catch (org.xml.sax.SAXParseException spe) { } catch (org.xml.sax.SAXException se) { } SAX & DOM
DOM con Xerces • Gli elementi del DOM sono contenuti nel namespace org.w3c.xml • Tutte le interfacce sono implementate esattamente come richiesto dalla specifica sotto forma di interfacce Java. import org.w3c.dom.Document; import org.w3c.dom.Element; import org.apache.xerces.dom.DocumentImpl; … Document doc = new DocumentImpl(); Element root = doc.CreateElement(“HTML”); Element body = doc.CreateElement(“Body”); body.setAttribute(“bgcolor”,”red”); root.appendChild(body); doc.appendChild(root); DocumentImpl è la classe che implementa l’interfaccia Document in xerces (non si può istanziare direttamente Document: è un’interfaccia!) SAX & DOM
Parsing XML con Xerces • Il parser DOM di Xerces è rapresentato dalla classe org.apache.xerces.parsers.DOMParser import org.apache.xerces.parsers.DOMParser; import org.w3c.dom.Document; DOMParser parser = new DOMParser(); try { parser.setFeature("http://xml.org/sax/features/validation", true); } catch (org.xml.sax.SAXNotRecognizedException ex ) { } catch (org.xml.sax.SAXNotSupportedException ex ) { } try { parser.parse(filename); } catch (java.io.IOException ioe) { } catch (org.xml.sax.SAXParseException spe) { } catch (org.xml.sax.SAXException se) { } Document doc = parser.getDocument(); SAX & DOM
Riferimenti • Apache XML Project (xalan, xerces)http://xml.apache.org • Java JAXP Tutorialhttp://java.sun.com/webservices/jaxp/docs.html • SAXhttp://www.saxproject.org/ • Specifiche DOM dal W3Chttp://www.w3.org/DOM/ SAX & DOM