JDOM
è una API open source, sviluppata da Brett McLaughlin
e Jason Hunter, giunta al momento alla versione beta
8. L'idea alla base di JDOM è quella di fornire
uno strumento per la gestione di documenti XML con i
meccanismi che si aspetterebbe uno sviluppatore Java.
Si osservi che nonostante JDOM sia rivolto agli sviluppatori
Java è comunque una API che interagisce con SAX
e DOM; i programmi sviluppati con JDOM possono quindi
ricevere in input documenti XML da un parser SAX/DOM
e analogamente possono generare un documento DOM o uno
stream di eventi SAX.
Un
documento JDOM
Un documento XML viene rappresentato come un'istanza
della classe org.jdom.Document; JDOM fornisce anche
l'analogo delle interfacce DOM come classi Java ma si
osservi che la gerarchia di classi JDOM non ha alcuna
relazione diretta con DOM, ad esempio la classe Node
di JDOM non implementa l'interfaccia Node di DOM.
La
prima caratteristica Java-oriented di JDOM che lo sviluppatore
incontra è il poter creare gli oggetti direttamente
col proprio costruttore, senza la necessità di
utilizzare metodi factory. Per creare ad esempio un
oggetto org.jdom.Element che rappresenta un tag <Document>
è quindi sufficiente scrivere
Element
e = new Element("Document");
Parsing
Per il parsing di documenti XML JDOM fornisce i builder,
oggetti che costruiscono un documento a partire da diverse
sorgenti dati come file, InputStream e InputSource.
Sono definiti due tipi di builder, DOMBuilder e SAXBuilder.
Come è evidente dal nome DOMBuilder carica un
documento a partire da un oggetto org.w3c.dom.Document
mentre SAXBuilder sfrutta un parser SAX ed è
quindi più performante.
Il
seguente codice mostra come usare un SAXBuilder per
eseguire il parsing di un file istanziando un documento
JDOM:
SAXBuilder
builder = new SAXBuilder(true);
Document doc = builder.build(new File(args[0]));
// ...
Le
classi SAXBuilder e DOMBuilder hanno vari costruttori
in overloading che permettono di specificare quale parser
usare (il default è Xerces) e se eseguire o meno
la validazione del documento (il default è false).
I/O
di documenti JDOM
Avere un potente framework per l'elaborazione di documenti
XML è importante ma è altrettanto importante
gestire l'I/O di documenti in maniera pratica.
Per quanto riguarda l'input di documenti le varie versioni
in overloading del metodo build() coprono un ampio spettro
di possibilità. La classe DOMBuilder permette
inoltre di creare un documento JDOM a partire da un
documento DOM.
L'aspetto più interessante riguarda la gestione
dell'output che, come visto, in DOM è abbastanza
complicato. La classe org.jdom.output.XMLOutputter si
occupa appunto di questo ed ha un pratico metodo output()
che accetta come argomenti un documento JDOM e un java.io.OutputStream.
Ad esempio per serializzare un documento su standard
output bastano le seguenti due righe di codice
XMLOutputter
outputter = new XMLOutputter();
outputter.output(doc, System.out);
Per
ottenere una stringa si usa invece il metodo outputString():
XMLOutputter
outputter = new XMLOutputter();
String str = outputter.outputString(doc);
La
classe SAXOutputter permette di generare uno stream
di eventi SAX:
ContentHandler
handler = ...;
SAXOutputter outputter = new SAXOutputter(handler);
outputter.output(doc);
Per
ottenere un org.w3c.dom.Document a partire da un documento
JDOM si usa invece l'apposita classe DOMOutputter:
org.jdom.Document
jdoc = ...;
org.w3c.dom.Document doc;
DOMOutputter
outputter = new DOMOutputter();
doc = outputter.output(jdoc);
Costruzione
di un documento JDOM
Facendo riferimento al seguente documento XML
<todolist>
<item>
<number>1</number>
<priority>6</priority>
<description>Leggere la posta</description>
<state>2</state>
</item>
<item>
<number>2</number>
<priority>9</priority>
<description>Riunione</description>
<state>2</state>
</item>
<item>
<number>3</number>
<priority>8</priority>
<description>Andare a correre nel parco</description>
<state>1</state>
</item>
</todolist>
ecco
un esempio di costruzione di un documento JDOM in maniera
'manuale', ovvero senza eseguire il parsing di una qualche
sorgente dati, e sua serializzazione su standard output:
package
com.mokabyte.javaxml.jdom;
import
java.io.*;
import org.jdom.*;
import org.jdom.output.*;
public
class JDOMCreation {
public static void main(String[] args) {
Element root = new Element("todolist"), item;
Document doc = new Document(root);
item = buildItem("1", "6", "Leggere
la posta", "2");
root.addContent(item);
item = buildItem("2", "9", "Riunione",
"2");
root.addContent(item);
item = buildItem("3", "8", "Andare
a correre nel parco", "1");
root.addContent(item);
try {
// serializzazione su standard output
XMLOutputter outputter = new XMLOutputter();
outputter.setNewlines(true);
outputter.setIndent(" ");
outputter.output(doc, System.out);
} catch(IOException e) {
System.err.println("Errore durante la serializzazione
del documento");
e.printStackTrace();
}
}
private final static Element buildItem(String number,
String priority,
String description,
String state) {
Element item = new Element("item"),
numberEl = new Element("number"),
priorityEl = new Element("priority"),
descriptionEl = new Element("description"),
stateEl = new Element("state");
numberEl.setText(number);
priorityEl.setText(priority);
descriptionEl.setText(description);
stateEl.setText(state);
item.addContent(numberEl);
item.addContent(priorityEl);
item.addContent(descriptionEl);
item.addContent(stateEl);
return item;
}
}
Il
metodo buildItem() costruisce un elemendo JDOM corrispondente
ad un'attività della todo-list:
- si
crea un elemento item;
- si
creano i vari elementi corrispondenti ai dati di un'attività
(numero, priorità, descrizione e stato);
- si
impostano i valori mediante il metodo setText() di
Element;
- si
'appendono' gli elementi contenenti i dati all'elemento
item, ritornato poi come risultato.
Si
noti come a differenza di DOM il valore di un elemento
non venga gestito come un nodo figlio da appendere ma
in maniera molto più pratica mediante un apposito
metodo, come fosse una sua proprietà.
Accesso
agli elementi di un documento
Il modello a oggetti di JDOM permette di navigare la
struttura di un documento in maniera molto semplice;
ad esempio dato un Document è possibile accedere
all'elemento radice con:
Element
root = doc.getRootElement();
A
questo punto si può accedere alla lista di tutti
i nodi figli
List
childrenList = root.getChildren();
o
a tutti i nodi figli aventi lo stesso nome
List
childrenList = root.getChildren("CHAPTER");
Le
precedenti linee di codice sono molto semplice e allo
stesso tempo dimostrano quanto JDOM sia un tool vicino
allo sviluppatore Java: il metodo getChildren() ritorna
un oggetto java.util.List che lo sviluppatore può
utilizzare con gli idiomi a cui è abituato. Le
collezioni ritornate dai metodi di JDOM sono inoltre
aggiornabili e le modifiche si ripercuotono sul Document
corrispondente. Ad esempio con
childrenList.add(new
Element("PARAGRAPH"));
si
aggiunge un nodo discendente all'elemento CHAPTER.
Per accedere ad un singolo nodo figlio si usa il metodo
getChild(); in questo caso si accede al primo nodo CHAPTER
partendo dalla radice del documento
Element
e = root.getChild("CHAPTER");
Per
accedere al contenuto di un elemento si usa il metodo
getContent()
String
content = e.getContent();
Utilizzando
DOM si sarebbe invece dovuto scrivere
String
content = e.getFirstChild().getNodeValue();
Il
seguente esempio mostra, una volta letto il documento
XML visto in precedenza e creato il corrispondente documento
JDOM, come accedere agli elementi in esso contenuti:
package
com.mokabyte.javaxml.jdom;
import
org.jdom.*;
import org.jdom.input.SAXBuilder;
import java.io.File;
import java.util.*;
public
class JDOMTest {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Utilizzo: java com.mokabyte.javaxml.jdom.JDOMTest
<file>");
return;
}
try {
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(new File(args[0]));
List children = doc.getRootElement().getChildren();
String number, priority, description, state;
Iterator iterator = children.iterator();
while(iterator.hasNext()) {
Element item = (Element)iterator.next();
number = item.getChildText("number");
priority = item.getChildText("priority");
description = item.getChildText("description");
state = item.getChildText("state");
System.out.println("Attivita' " + number);
System.out.println("\tPriorita': " + priority);
System.out.println("\tDescrizione: " + description);
System.out.println("\tStato: " + state);
}
} catch(JDOMException e) {
System.err.println("Errore durante il parsing del
documento " + args[0]);
e.printStackTrace();
}
}
}
L'output
del programma precedente è
Attivita'
1
Priorita': 6
Descrizione: Leggere la posta
Stato: 2
Attivita' 2
Priorita': 9
Descrizione: Riunione
Stato: 2
Attivita' 3
Priorita': 8
Descrizione: Andare a correre nel parco
Stato: 1
Attributi
Nel caso in cui l'elemento abbia un attributo lo si
può ottenere come stringa
String
attrValue = e.getAttributeValue("name");
o
come istanza della classe Attribute
Attribute
attribute = e.getAttribute("name");
String value = attribute.getValue();
E'
inoltre possibile accedere al valore tipizzato di un
attributo mediante una serie di metodi specifici. Ad
esempio per ottenere il valore di un attributo numerico
è possibile scrivere
int
length = attribute.getAttribute("length").getIntValue();
Per
impostare il valore di un attributo si scriverà
invece
e.setAttribute("height",
"20");
Conclusioni
JDOM è uno strumento veramente interessante per
lo sviluppatore Java:
- il
suo modello a oggetti è molto più pratico
di DOM. Ad esempio il poter creare gli oggetti direttamente
con il costruttore è sicuramente più
immediato che usare metodi factory;
- l'utilizzo
delle collection semplifica inoltre notevolmente il
codice necessario ed è un idioma di programmazione
molto vicino al programmatore Java.
Il futuro di JDOM è molto promettente anche
perchè il progetto è stato proposto
come Java Specification Request e potrebbe essere
incluso in una delle prossime versioni di Java.
Bibliografia
[1] JDOM - http://www.jdom.org
[2] MokaByte - "Manuale pratico di Java",
HOPS Libri
[3] Elliotte Rusty Harold - "Processing XML with
Java", http://www.cafeconleche.org/books/xmljava/chapters/index.html
[4] Wes Biggs, Harry Evans - "Simplify XML Programming
with JDOM", IBM developerWorks
Risorse
Scarica
qui i sorgenti presentati
nell'articolo
Andrea
Giovannini si occupa di architetture per applicazioni
enterprise Web-based con tecnologia J2EE, con particolare
interesse per XML.
|