SAX & DOM Laurea Magistrale in Informatica Reti 2 (2005/06) dott. Francesco De Angelis
SAX & DOM2 Agenda Introduzione e confronto approcci SAX DOM
Introduzione e confronto approcci
SAX & DOM4 Il parser Il parser si occupa di: Recuperare il documento XML Caricare i dati in memoria Presentare allapplicazione uninterfaccia di alto livello (opzionalmente) fornire servizi di validazione (opzionalmente) fornire servizi di ricerca XMLDTD XML parser Applicazione XSD
SAX & DOM5 Approccio ad eventi Il parser scandisce lintero file Per ogni elemento informa lapplicazione tramite la tecnica del callback Francesco De Angelis Alberto Polzonetti... XML Parser Applicazione libroautore nome … t
SAX & DOM6 Approccio del modello Il parser costruisce una struttura ad albero che rappresenta il documento Fornisce allapplicazione delle API per navigare lalbero Francesco De Angelis Alberto Polzonetti... XML Parser Applicazione librotitolo=… autore nome cognome attr
SAX & DOM7 Confronto tra gli approcci Approccio ad eventiApproccio del modello Pro E molto leggero Il programmatore può implementare solo le funzionalità necessarie fornisce allapplicazione un modello ricco del documento mantiene una rappresentazione completa e durevole in memoria Contro Interfaccia troppo semplice = si richiede più codice nellapplicazione Nessun supporto per operare sul documento richiede una occupazione di memoria per tutto il documento
SAX & DOM8 JAXP Java API for XML Processing (JAXP) Supporto standard di SUN per lelaborazione 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 & DOM9 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 dellimplementazione DOM Le librerie Java usano SAX per leggere un file XML e creare il DOM corrispondente! SAX e DOM
Simple API for XML
SAX & DOM11 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) è 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 & DOM12 Utilità e Limiti di SAX Il parser SAX non 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 & DOM13 Gestire gli Eventi SAX Per ricevere le notifiche dal parser SAX, il codice deve registrare nel parser una classe org.xml.sax.DefaultHandler che implementa linterfaccia org.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 dellelemento e del suo namespace, nonché la lista degli attributi associati.
SAX & DOM14 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); } Lhandler di SAX
SAX & DOM15 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); } La classe DefaultHandler implementa linterfaccia permettendo allapplicazione di ridefinire (override) solo i metodi desiderati Lhandler di SAX
SAX & DOM16 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); } Il client utilizza la classe di Factory per recuperare il parser Al parser viene chiesto di parsare il file come un processo autonomo Utilizzo dellhandler SAX
SAX & DOM17 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 & DOM18 ErrorHandler Interface ErrorHandler { void error(SAXParseException exception) void fatalError(SAXParseException exception) void warning(SAXParseException exception) } Class SAXParseException { int getColumnNumber() int getLineNumber() String getPublicId() String getSystemId() } ü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 & DOM19 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 & DOM20 SAX con Xerces import org.apache.xerces.parsers.SAXParser; import org.xml.sax.helpers.DefaultHandler; SAXParser sxp = new SAXParser(); try { sxp.setFeature( " 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) { }
Document Object Model
SAX & DOM22 E unAPI (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 Definizione di DOM
SAX & DOM23 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 Definizione di DOM
SAX & DOM24 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 La specifica attuale è al Livello 2, tuttavia alcune specifiche del Livello 3 sono già raccomandazioni del W3C. I livelli di DOM
SAX & DOM25 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, lutente che accede al documento tramite linterfaccia DOM, lo vedrà effettivamente come un albero. Il DOM definisce solo la vista logica: non specifica come debbano essere effettivamente strutturati in memoria. La struttura di DOM
SAX & DOM26 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 & DOM27 La vista del DOM su XML Santana Corazon Espinado First Hit from the Album 4 36 Santana Corazon Espinado First Hit from the Album 436 track=9 document
SAX & DOM28 import org.w3c.dom.*; import javax.xml.parsers.*; import org.xml.sax.*; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse("libro.xml"); Definizione DOM standard Implementazione di JAXP DOM usa SAX Il DOM di JAXP è definito nel package org.w3c.dom Fornisce uninterfaccia standard che si appoggia su implementazioni differenti Sono disponibili implementazioni differenti (SUN, Apache, Oracle) Limplementazione di SUN è in javax.xml.parsers Caricamento di un DOM
SAX & DOM29 Element root = doc.getDocumentElement(); System.out.println(root.getNodeName()); Estrazione del nodo radice e stampa del nome del nodo Nodi figli Attributi 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()); Navigazione di un DOM
SAX & DOM30 n.getNodeType() == n.ELEMENT_NODE Tipizzazione tramite attributi di descrizione Tipo di nodonodeNamenodeValueattributes ElementNome del tagnullNamedNodeMap AttrNome dellattributoValore dellattributonull Text#textTesto associatonull CDATASection#cdata-sectionTesto associatonull EntityReferenceNome dellentitànull EntityNome dellentitànull ProcessingInstructionValore dellattributo targetContenuto escluso lattributo targetnull Comment#commentTesto associatonull Document#documentnull DocumentTypeNome del tipo di documentonull DocumentFragment#document-fragmentnull NotationNome della NOTATIONnull Tipizzazione
SAX & DOM31 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à In maniera analoga è possibile abilitare la gestione dei namespace factory.setValidating(true); factory.setAttribute(" " factory.setNamespaceAware(true); Validazione e Namespace
SAX & DOM32 Eredita la gestione degli errori di SAX lapplicazione 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()); Error Handling
SAX & DOM33 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, ); Browsing e stampa
SAX & DOM34 <librotitolo=Corso di XML" xmlns:xsi=" xmlns=" xsi:schemaLocation=" Francesco De Angelis Alberto Polzonetti... XML in ingresso Esempio
SAX & DOM35 libro ( titolo=Corso di XML xmlns= xmlns:xsi= xsi:schemaLocation= libro3b.xsd) - autore () - - nome () Francesco - - cognome () De Angelis - autore () - - nome () Alberto - - cognome () Polzonetti - capitolo ( titolo=SAX and DOM) Output Esempio
SAX & DOM36 DOM permette di inserire nuovi elementi nellalbero Element root = doc.getDocumentElement(); Element cap = doc.createElement("capitolo"); cap.setAttribute("titolo", "Introduzione"); cap.appendChild(doc.createTextNode("... testo...")); Node capitolo = doc.getElementsByTagNameNS(" "capitolo").item(0); root.insertBefore(cap, capitolo); doc.normalize(); Creazione del nodo Creazione dellattributo Ricerca del primo capitolo presente Inserimento normalizzazione. Es: unisce nodi di testo consecutivi Modifica dellalbero
SAX & DOM37 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 Linterfaccia di Node include le operazioni di base eseguibili su ogni tipo di oggetto (indipendentemente dal suo tipo specifico) in un documento XML
SAX & DOM38 Tipi di Nodo (nodeType) I tipi specifici per i nodi sono identificati dalle costanti dellinterfaccia 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 è unentità (= 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 & DOM39 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 & DOM40 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 loperazione non sia disponibile (ad esempio, appendChild su un nodo Text), viene generata uneccezione di tipo DOMException.
SAX & DOM41 Interfaccia Element 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 dallelemento. 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(); };
SAX & DOM42 Interfaccia Attr üI valori per name e value sono accessibili anche attraverso i metodi getName e getValue dellinterfaccia Node üLattributo specified è false se lattributo 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, lattributo è true interface Attr { readonly attribute DOMString name; readonly attribute boolean specified; attribute DOMString value; };
SAX & DOM43 NodeList e NamedNodeMap 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; }; interface NodeList { 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 (lattributo nodeName di Node).
SAX & DOM44 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); }; üLoggetto Document fornisce i metodi per creare i nodi che compongono il documento XML! üdocumentElement rappresenta lelemento radice del documento.
SAX & DOM45 Il DOM con Java: JAXP JAXP è unAPI generica offerta da Java per manipolare il DOM. In realtà, JAXP è uninterfaccia astratta che deve poggiarsi su una vera implementazione del DOM fornita da terze parti. E possibile usare anche direttamente limplementazione del DOM. Noi faremo riferimento al pacchetto Xerces dellApache XML Project, di gran lunga il più diffuso e perfezionato.
SAX & DOM46 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 & DOM47 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 & DOM48 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 linterfaccia Document in xerces (non si può istanziare direttamente Document: è uninterfaccia!)
SAX & DOM49 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(" 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 & DOM50 Riferimenti Apache XML Project (xalan, xerces) Java JAXP Tutorial SAX Specifiche DOM dal W3C