SAX & DOM
Laurea Magistrale Laurea Magistrale in Informaticain Informatica
Reti 2 (2005/06)Reti 2 (2005/06)
dott. Francesco De [email protected]
SAX & DOM 2
Agenda
Introduzione e confronto approcci SAX DOM
Introduzione e confronto approcci
SAX & DOM 4
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
XMLDTD
XML parser
Applicazione
XSD
SAX & DOM 5
Approccio ad eventi
Il parser scandisce l’intero file Per ogni elemento informa l’applicazione tramite
la tecnica del callback
<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>
XML Parser
Applicazione
libro autore nome…
t
SAX & DOM 6
Approccio del modello
Il parser costruisce una struttura ad albero che rappresenta il documento
Fornisce all’applicazione delle API per navigarel’albero
<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>
XML Parser
Applicazione
libro titolo=“…”
autore
nome
cognome
attr
SAX & DOM 7
Confronto tra gli approcci
Approccio ad eventi Approccio del modello
Pro E’ molto “leggero”
Il programmatore può implementare solo le funzionalità necessarie
fornisce all’applicazione un modello ricco del documento
mantiene una rappresentazione completa e durevole in memoria
Contro Interfaccia troppo semplice = si richiede più codice nell’applicazione
Nessun supporto per operare sul documento
richiede una occupazione di memoria per tutto il documento
SAX & DOM 8
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 9
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 e DOM
Simple API for XML
SAX & DOM 11
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 12
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 & DOM 13
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 l’interfaccia 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
dell’elemento e del suo namespace, nonché la lista degli attributi associati.
SAX & DOM 14
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);
}
L’handler di SAX
SAX & DOM 15
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 l’interfaccia permettendo all’applicazione di ridefinire (override) solo i metodi desiderati
L’handler di SAX
SAX & DOM 16
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 dell’handler SAX
SAX & DOM 17
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 18
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 & DOM 19
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 20
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) {}
Document Object Model
SAX & DOM 22
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
Definizione di DOM
SAX & DOM 23
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 & DOM 24
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.
I livelli di DOM
SAX & DOM 25
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.
La struttura di DOM
SAX & DOM 26
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 27
La vista del DOM su XML
<song track="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>
<song>
<comment><artist> <title> <length>
<minutes> <seconds><name>
Santana
Corazon Espinado
First Hit from the Album
4 36
track=9
document
SAX & DOM 28
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 standardImplementazione
di JAXPDOM usa SAX
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
Caricamento di un DOM
SAX & DOM 29
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 & DOM 30
n.getNodeType() == n.ELEMENT_NODE
Tipizzazione tramite attributi di descrizione
Tipo di nodo nodeName nodeValue attributes
Element Nome del tag null NamedNodeMap
Attr Nome dell’attributo Valore dell’attributo null
Text “#text” Testo associato null
CDATASection “#cdata-section” Testo associato null
EntityReference Nome dell’entità null null
Entity Nome dell’entità null null
ProcessingInstruction Valore dell’attributo target Contenuto escluso l’attributo target null
Comment “#comment” Testo associato null
Document “#document” null null
DocumentType Nome del tipo di documento null null
DocumentFragment “#document-fragment” null null
Notation Nome della NOTATION null null
Tipizzazione
SAX & DOM 31
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);
Validazione e Namespace
SAX & DOM 32
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());
Error Handling
SAX & DOM 33
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 & DOM 34
<?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>
XML in ingresso
Esempio
SAX & DOM 35
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) - - ...
Output
Esempio
SAX & DOM 36
DOM permette di inserire nuovi elementi nell’albero
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 del nodo
Creazione dell’attributo
Ricerca del primo capitolo presente
Inserimentonormalizzazione. Es: unisce
nodi di testo consecutivi
Modifica dell’albero
SAX & DOM 37
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 38
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 39
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 40
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 41
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 dall’elemento.
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 & DOM 42
Interfaccia Attr
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
interface Attr {readonly attribute DOMString name;readonly attribute boolean specified;attribute DOMString value;
};
SAX & DOM 43
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 (l’attributo nodeName di Node).
SAX & DOM 44
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 45
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 46
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 47
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 48
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 49
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 50
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/