XML Parser

Per manipolare un file XML attraverso Java sarebbe necessario aprire il file XML e il DTD (Document Type Definition), creare attraverso quest’ultimo una tabella dei nodi e interpretare il documento per estrarne i dati. Fortunatamente esistono classi che lo fanno per noi: i parser, capaci di interpretare la struttura ad albero di XML e di renderla gestibile da Java.

Una volta che il file è stato elaborato dal parser, si ottiene un oggetto con struttura DOM (Document Object Model). DOM è un insieme di interfacce indipendenti dalla piattaforma e dal linguaggio che permette di accedere e modificare struttura e dati di un documento XML; è definito dal consorzio W3C.

Esistono diversi parser, fra cui IBM XML Parser for Java e Sun ProjectX XML Parser. Il loro impiego è molto simile e cambia soprattutto il modo di caricare il file XML. In questo articolo utilizzeremo il parser Sun e convertiremo in memoria un documento XML in un oggetto Java.

Conversione di un oggetto XML in un oggetto Java

Il nostro DTD è molto semplice:

<?xml version="1.0"?>
<!DOCTYPE MOKABYTE [
  <!ELEMENT MOKABYTE (ARTICOLO)*>
  <!ELEMENT ARTICOLO (TITOLO, AUTORE, MESE)>
  <!ELEMENT TITOLO (#PCDATA)>
  <!ELEMENT AUTORE (#PCDATA)>
  <!ELEMENT MESE (#PCDATA)>
]>

La struttura corrispondente è:

MOKABYTE
└── ARTICOLO
    ├── TITOLO (testo)
    ├── AUTORE (testo)
    └── MESE (testo)

MOKABYTE può contenere un numero qualsiasi di elementi ARTICOLO. Con una terminologia da database, potremmo dire che la tabella MOKABYTE contiene record ARTICOLO costituiti dai campi TITOLO, AUTORE e MESE.

Per creare un documento DOM a partire da un file XML importiamo le librerie necessarie:

import org.w3c.dom.*;
import com.sun.xml.tree.*;
import java.io.*;

Il primo import mette a disposizione la classe Document, che conterrà il file XML convertito dal parser:

try {
    // Il percorso del file XML da utilizzare.
    String xmlfile = "xmlfile.xml";
    // Converte il file in un input stream.
    InputStream is = new FileInputStream(xmlfile);
    // Effettua il parsing del file e crea il documento.
    Document doc = XmlDocumentBuilder.createXmlDocument(is);
} catch (Exception ex) {
    // Segnala eventuali errori.
}

A questo punto abbiamo un oggetto DOM e possiamo estrarne le informazioni. Supponiamo che il file XML contenga:

<?xml version="1.0"?>
<MOKABYTE>
  <ARTICOLO>
    <AUTORE>Mauro Molino</AUTORE>
    <TITOLO>XML e Java</TITOLO>
    <MESE>Aprile</MESE>
  </ARTICOLO>
  <ARTICOLO>
    <AUTORE>Giovanni Puliti</AUTORE>
    <TITOLO>Web dinamico con JSP</TITOLO>
    <MESE>Aprile</MESE>
  </ARTICOLO>
  <ARTICOLO>
    <AUTORE>Marco Molinari</AUTORE>
    <TITOLO>Java 3D API</TITOLO>
    <MESE>Aprile</MESE>
  </ARTICOLO>
</MOKABYTE>

Sono presenti tre record di tipo ARTICOLO. Possiamo sapere quanti elementi base del file esistono — gli elementi rappresentati da ROOTELEMENTTAG, il cui unico padre è il documento — con il metodo getSize() della classe XmlUtils:

int numeroArticoli = XmlUtils.getSize(doc, ROOT_ELEMENT_TAG);

Possiamo poi estrarre un record e leggerne titolo, autore e mese:

Element articolo = XmlUtils.getElement(doc, ROOT_ELEMENT_TAG, 1);
String titolo = XmlUtils.getValue(articolo, "Titolo");
String autore = XmlUtils.getValue(articolo, "Autore");
String mese = XmlUtils.getValue(articolo, "Mese");

Supponiamo ora di avere un semplice oggetto Java capace di ospitare i dati prelevati dal file XML:

public class Articolo {
    protected String Titolo, Autore, Mese;
    public void setTitolo(String tit) {
        Titolo = tit;
    }
    public void setAutore(String aut) {
        Autore = aut;
    }
    public void setMese(String mes) {
        Mese = mes;
    }
}

La struttura è identica a quella del file XML, ma espressa come oggetto Java. È sufficiente scrivere:

Articolo artic = new Articolo();
artic.setTitolo(titolo);
artic.setAutore(autore);
artic.setMese(mese);

Abbiamo così convertito una struttura DOM in un oggetto Java, che possiamo manipolare senza interagire ulteriormente con il DOM. Per esempio, un file XML contenente un elenco di libri può essere importato in corrispondenti oggetti Java, visualizzato in una griglia, modificato e infine ritrasferito in XML per la pubblicazione sul web.

Conversione di un oggetto Java in un oggetto XML

Il passaggio inverso è altrettanto semplice. Il DTD può essere inserito direttamente nel file XML. Supponiamo che la classe Articolo disponga anche dei seguenti metodi:

String getTitolo() {
    return Titolo;
}
String getAutore() {
    return Autore;
}
String getMese() {
    return Mese;
}

Questi metodi forniscono i dati necessari a popolare il file XML. Possiamo ora implementare una classe che prende i dati da un oggetto Articolo, li trasforma in XML e genera anche la porzione DTD:

import java.io.*;
import org.w3c.dom.*;
import com.sun.xml.tree.*;
public class creaXML {
    public static String filexml;
    public static void main(String[] args) {
        Articolo articolo = new Articolo();
        articolo.setTitolo("Titolo1");
        articolo.setAutore("Autore1");
        articolo.setMese("Mese");
        try {
            FileOutputStream os = new FileOutputStream(filexml);
            PrintWriter pr = new PrintWriter(os);
            pr.println("<?xml version='1.0'?>");
            pr.println("<!DOCTYPE MOKABYTE [");
            pr.println("<!ELEMENT MOKABYTE (ARTICOLO)*>");
            pr.println("<!ELEMENT ARTICOLO (TITOLO,AUTORE,MESE)>");
            pr.println("<!ELEMENT TITOLO (#PCDATA)>");
            pr.println("<!ELEMENT AUTORE (#PCDATA)>");
            pr.println("<!ELEMENT MESE (#PCDATA)>");
            pr.println("]>");
            pr.println("<MOKABYTE>");
            pr.println("  <ARTICOLO>");
            pr.println("    <TITOLO>" + articolo.getTitolo() + "</TITOLO>");
            pr.println("    <AUTORE>" + articolo.getAutore() + "</AUTORE>");
            pr.println("    <MESE>" + articolo.getMese() + "</MESE>");
            pr.println("  </ARTICOLO>");
            pr.println("</MOKABYTE>");
            pr.flush();
            pr.close();
        } catch (Exception ex) {
            System.out.println(ex);
        }
    }
}

Il codice è ampiamente commentato. Anche in questo caso la procedura è semplice: l’interconversione fra Java e XML è pressoché immediata, non richiede manipolazioni complesse e fa incontrare due tecnologie di grande attualità.

Conclusioni

Abbiamo visto come, con pochissimo codice, sia possibile convertire strutture di dati dal mondo Java a quello XML. La rapidità con cui proliferano strumenti d’integrazione conferma la stretta affinità tra le due tecnologie.

Potrebbe essere interessante sperimentare l’utilizzo congiunto di Java e PGML (Precision Graphics Markup Language), un linguaggio XML dedicato alla grafica vettoriale 2D sul web. Con la stessa logica usata per mappare strutture XML in Java e viceversa, è possibile mappare in Java anche strutture grafiche PGML: l’unico limite è la fantasia.