Leggere un file XML in Java con la libreria JDOM

Leggere un file XML in Java con la libreria JDOM

In questo post vedremo come poter leggere e scrivere un file XML in Java utilizzando la libreria JDOM. JDOM è una API Open Source, sviluppata da Brett McLaughlin e Jason Hunter, la quale interagisce con gli standard già esistenti quali SAX (Simple Api for XML) e DOM (Document Object Model), il cui obiettivo non è quello di creare uno strato di astrazione aggiuntivo o di potenziamento delle funzionalità di queste API, ma bensì quello di fornire un modello e degli strumenti che siano più familiari ad un programmatore Java, rendendo meno complessa e meno esigente di risorse la manipolazione di file XML. La versione che prendiamo in esame in questo articolo è la 1.1.1 (la più recente nel momento in cui scriviamo) nella quale è stato aggiunto il supporto alla Virtual Machine Dalvik (la VM di Android).

Installazione ambiente Java in Windows
Sviluppare un’applicazione JSF con JBoss e Richfaces
Come dimensionare l’Heap Size di un’applicazione Java

Faremo ora un esempio concreto di utilizzo utilizzando Eclipse. Come sempre configuriamo un Progetto Java all’interno di Eclipse  cliccando su File -> New -> Java Project:

Nominiamo il nostro progetto TestJdom

poi creiamo una cartella lib e vi copiamo la libreria jdom.jar, non dimentichiamoci poi di includerla nel Build Path del nostro progetto: click col tasto destro -> Build Path -> Configure Build Path):

Includiamo JDOM nel Build Path del progetto

Creiamo una classe Java al suo interno e copiamo il codice seguente, il quale permette di leggere un file XML e di stampare i valori ed il tipo dei Nodi incontrati durante la visita del documento XML.


package it.appuntisoftware;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import org.jdom.Attribute;
import org.jdom.CDATA;
import org.jdom.Comment;
import org.jdom.DocType;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Text;
import org.jdom.input.SAXBuilder;

public class ReadXML {
public static void main(String args[]){
SAXBuilder builder = new SAXBuilder();
Document doc;
try {
doc = builder.build("rubrica.xml");
listNodes(doc,0);
} catch (IOException e) {
e.printStackTrace();
} catch (JDOMException e) {
e.printStackTrace();
}
}

public static void listNodes(Object o, int depth) {
stampaSpazi(depth);
if (o instanceof Element) {
Element element = (Element) o;
if(((Element) o).isRootElement())
System.out.println("Root Element:"+ ((Element) o).getName());
else
System.out.println("Element: " + element.getName());
//Itera sugli eventuali attributi dell'elemento
if(!((Element) o).getAttributes().isEmpty()){
Iterator iter =element.getAttributes().iterator();
while (iter.hasNext()) {
Object attribute = iter.next();
listNodes(attribute, depth+1);

}
}
//Itera sui figli dell'elemento
List children = element.getContent();
Iterator iterator = children.iterator();
while (iterator.hasNext()) {
Object child = iterator.next();
listNodes(child, depth+1);
}
}
else if (o instanceof Document) {
System.out.println("Document");
Document doc = (Document) o;
List children = doc.getContent();
Iterator iterator = children.iterator();
while (iterator.hasNext()) {
Object child = iterator.next();
listNodes(child, depth+1);
}
}
else if (o instanceof Comment) {
System.out.println("Comment:");
System.out.println(((Comment) o).getText());
}
else if (o instanceof CDATA) {
System.out.print("Sezione CDATA:");
// CDATA è una sottoclasse di Text di conseguenza questo test
// va prima di quello per Text.
System.out.println(((CDATA) o).getText());
}
else if (o instanceof Text) {
System.out.print("Text:");
System.out.println(((Text) o).getValue());
}
else if (o instanceof Attribute) {
System.out.print("Attribute:");
System.out.print(((Attribute) o).getQualifiedName());
System.out.println(((Attribute) o).getValue());
}
else if (o instanceof DocType) {
System.out.print("DocType:");
System.out.print(((DocType) o).getElementName());
System.out.println(((DocType) o).getPublicID());
}
else {
System.out.println("Tipo non previsto: " + o.getClass());
}
}
private static void stampaSpazi(int n) {
for (int i = 0; i < n; i++) {
System.out.print(' ');
}
}
}

Possiamo provare questo programma utilizzando questo file XML, nel quale abbiamo inserito i tipi di Nodi più variegati possibili:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rubrica [
<!ENTITY FS "Fisico">
]>
<rubrica xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- Rubrica Contatti -->
<contatto id="1">
<![CDATA[<1° Contatto>]]>
<nome>Enrico</nome>
<cognome>Fermi</cognome>
<professione>&FS;</professione>
</contatto>
<contatto id="2">
<![CDATA[<2° Contatto>]]>
<nome>Albert</nome>
<cognome>Einstein</cognome>
</contatto>
<contatto id="3">
<![CDATA[<3° Contatto>]]>
<nome>Isaac</nome>
<cognome>Newton</cognome>
</contatto>
<contatto id="4">
<![CDATA[<4° Contatto>]]>
<nome>Johannes</nome>
<cognome>Stark</cognome>
</contatto>
</rubrica>

una volta lanciato il programma vedremo apparire sulla Console in output numerose diciture di tipo Text: con degli spazi vuoti, ciò è dovuto al fatto che il Parser considera come nodo Text anche i simboli di andata a capo ( gli “n” per farla breve) e li valorizza correttamente come vuoti, per evitare ciò il file XML non dovrebbe avere queste rimandi a capo ma dovrebbe essere un’unica sequenza di tag (poco leggibile se  fosse riportata su questo articolo). Fatta questa precisazione di carattere per lo più estetico ma che non cambia nulla dal punto di vista funzionale, entriamo nel dettaglio dell’esempio: una volta ottenuto il Document dal SAXBuilder, utilizziamo una funzione ricorsiva per scorrere tutti i nodi dell’albero XML. A seconda del nodo incontrato ne stampiamo il tipo ed il valore contenuto.

Nel caso di Nodi di tipo Element, verifichiamo se essi abbiano degli attributi e stampiamo a video sia il loro nome che il valore contenuto. Ogni elemento contatto ha poi un nodo di tipo CDATA che viene correttamente interpretato dalla libreria JDOM, infatti esso contiene dei caratteri quali le virgolette < e > ed il simbolo ° che darebbero errore se inseriti in un tag XML (in CDATA possiamo inserire qualsiasi carattere dato che essi vengono sempre interpretati come sequenze di caratteri).

Un’altra particolarità è data dalla presenza di un valore (&FS; presente nel tag <professione>) collegato ad un tag Entity (Entity Reference) , il quale viene correttamente interpretato e sostituito col valore della Entity (nel nostro caso il valore “Fisico”). Infine vengono correttamente stampati sia i valori dei Comment che del DocType.

PAGES

1 2

COMMENTS

WORDPRESS: 1
  • comment-avatar
    GoGoMoNkEy 11 anni ago

    Ti ringrazio per questo articolo! Mi è stato molto utile! 😀