Introduzione a XML in Java
Panoramica sull'elaborazione XML in Java: approcci DOM, SAX, StAX e JAXB con esempi pratici.
XML (Extensible Markup Language) è un formato testuale per rappresentare dati strutturati e gerarchici tramite tag annidati. Molto prima che JSON dominasse le API web, XML era lo standard predefinito per i file di configurazione, i formati di documento e lo scambio di messaggi — ed è ancora ovunque, dai file Maven pom.xml ai servizi SOAP fino ai documenti Office.
Java offre un supporto XML ricco e integrato nel JDK: non è necessaria alcuna libreria esterna per leggere o scrivere XML. I package javax.xml.parsers e org.w3c.dom, insieme a org.xml.sax e javax.xml.stream, forniscono tre distinti modelli di parsing. Questo capitolo illustra cosa è XML, quale modello di parsing scegliere e come XML si confronta con JSON — in modo che il resto di questa sezione (DOM, SAX e JAXB) si basi su fondamenta solide.
Questa pagina tratta:
- Come appare un documento XML e i termini che è necessario conoscere (elemento, attributo, radice, ben formato).
- I tre modelli di parsing del JDK — DOM, SAX e StAX — e quando ciascuno è adatto.
- Un esempio DOM eseguibile che utilizza solo classi JDK.
- Le differenze tra XML e JSON, per scegliere tra i due.
Come appare XML
Un documento XML è un albero di elementi. Ogni elemento ha un nome, attributi opzionali e contenuto testuale o elementi figli annidati. Esiste sempre esattamente un elemento radice che racchiude tutto.
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<book id="1" lang="en">
<title>Effective Java</title>
<price>45.00</price>
</book>
</catalog>Qui <catalog> è la radice, <book> è un elemento figlio con due attributi (id e lang), mentre <title> e <price> contengono testo. La dichiarazione XML nella prima riga indica la versione e la codifica dei caratteri. XML ben formato richiede che ogni tag di apertura sia chiuso e correttamente annidato.
I tre modelli di parsing
Il JDK offre tre modi per leggere XML, ciascuno con un diverso compromesso tra comodità e memoria. Scegliere quello giusto è la decisione XML più importante che si possa prendere.
| Modello | Stile | Memoria | Adatto per |
|---|---|---|---|
| DOM | Carica l'intero albero in memoria | Alta | Accesso casuale, modifica, documenti piccoli/medi |
| SAX | Invia eventi durante la scansione (callback) | Bassa | Documenti grandi, streaming in sola lettura |
| StAX | Estrae eventi su richiesta (cursore) | Bassa | Documenti grandi, con flusso di controllo più semplice |
DOM costruisce un albero completo in memoria che si può navigare liberamente e modificare. SAX attiva callback (startElement, characters, endElement) durante la lettura, senza mai tenere l'intero documento in memoria. StAX è anch'esso in streaming, ma consente al proprio codice di estrarre il prossimo evento quando è pronto, il che di solito è più facile da seguire rispetto alle callback di SAX.
DOM: l'albero in memoria
DOM è il modello più comodo quando i documenti sono abbastanza piccoli da stare in memoria. Si effettua il parsing una volta, poi si naviga o si interroga l'albero quante volte si vuole.
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = factory.newDocumentBuilder().parse("catalog.xml");
NodeList books = doc.getElementsByTagName("book");
System.out.println("Books: " + books.getLength());getElementsByTagName restituisce una NodeList live; si accede agli elementi tramite indice e si fa il cast dei nodi a Element per leggere attributi e testo dei figli. Il capitolo dedicato al parser XML DOM in Java illustra in dettaglio come navigare, modificare e scrivere l'albero.
By default the JDK parser resolves external entities, which exposes you to XXE (XML External Entity) attacks when parsing untrusted input. For production code that reads XML from outside your control, disable DTDs with factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); before creating the builder.
SAX e StAX: lo streaming
Quando un documento è troppo grande per stare in memoria, si usa lo streaming. SAX invia eventi a un handler fornito dall'utente:
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
DefaultHandler handler = new DefaultHandler() {
public void startElement(String uri, String local, String name, Attributes a) {
System.out.println("Start: " + name);
}
};
SAXParserFactory.newInstance().newSAXParser()
.parse("catalog.xml", handler);StAX fornisce un cursore che si avanza manualmente, il che molti trovano più chiaro:
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamConstants;
import java.io.FileReader;
XMLStreamReader r = XMLInputFactory.newInstance()
.createXMLStreamReader(new FileReader("catalog.xml"));
while (r.hasNext()) {
if (r.next() == XMLStreamConstants.START_ELEMENT) {
System.out.println("Start: " + r.getLocalName());
}
}Vedere il capitolo sul parser XML SAX in Java per una guida completa agli event handler. Se si preferisce evitare il parsing manuale dei nodi e mappare XML direttamente su oggetti Java, JAXB associa gli elementi a classi annotate.
Un esempio autonomo
L'esempio eseguibile qui sotto usa solo classi JDK — nessun Jackson o JAXB necessario. Effettua il parsing di un catalogo XML da una stringa in memoria con DOM, scorre gli elementi <book>, legge attributi e testo dei figli, e somma i prezzi.
Cosa ricavare dall'esecuzione:
- Il parsing DOM non richiede dipendenze esterne —
DocumentBuilderFactoryeorg.w3c.domsono inclusi nel JDK, motivo per cui il programma stampa i risultati senza nulla nel classpath. - Il nome dell'elemento radice stampato come
catalogconferma che esiste esattamente una radice che racchiude l'intero documento. getElementsByTagName("book")ha restituito unaNodeListdi lunghezza 2, quindi è possibile indicizzarla come una lista e fare il cast di ogni elemento aElement.- Gli attributi (
id) si leggono congetAttribute, mentre il contenuto testuale (title,price) si legge congetTextContent— sono tipi di dati diversi sullo stesso elemento. - Poiché l'intero albero è in memoria, sommare i prezzi di tutti i libri per ottenere
$83.50è solo un ciclo con accesso casuale — la comodità che rende DOM vantaggioso nonostante il costo in memoria.
XML o JSON?
XML e JSON risolvono lo stesso problema — scambiare dati strutturati — ma con compromessi diversi.
| Aspetto | XML | JSON |
|---|---|---|
| Sintassi | Tag verbosi, apertura e chiusura | Parentesi graffe e quadre compatte |
| Attributi | Sì (id="1") | No — tutto è una coppia chiave/valore |
| Commenti | Supportati (<!-- ... -->) | Non supportati |
| Schema/validazione | Maturo (XSD, DTD) | JSON Schema, meno diffuso |
| Supporto JDK | Integrato (javax.xml.*) | Nessuno integrato — richiede una libreria |
| Uso tipico oggi | Configurazione, documenti, SOAP, sistemi legacy | API web/REST, servizi moderni |
Scegliere XML quando è necessario consumare un formato XML esistente (un servizio SOAP, un pom.xml, un documento Office) o quando si necessita di attributi, commenti o validazione rigorosa tramite schema. Scegliere JSON per le nuove API web, dove le dimensioni ridotte e il supporto nativo del browser sono vincenti.
Passi successivi
- Parser XML DOM in Java — leggere, modificare e scrivere l'albero.
- Parser XML SAX in Java — eseguire lo streaming di documenti grandi con event handler.
- JAXB — mappare XML da e verso oggetti Java annotati.
- Introduzione a JSON in Java — l'alternativa moderna per i dati web.