MokaByte Numero 30  -  Maggio 1999
 
XML & Java
II parte
di 
Mauro Molino
Dopo aver introdotto nell'articolo del mese scorso alcuni principi di XML e della sua integrazione con Java, vediamo questo mese come il tutto avviene a livello di codice.
 


L'utilizzo congiunto di Java e XML abbiamo visto che in teoria e' abbastanza semplice. Diversamente da come spesso accade, in questo caso la pratica risulta altrettanto semplice, per cui con poco codice e' possibile ottenere una reale integrazione. Nel corso dell'articolo vedremo il codice strettamente necessario per poter cominciare a lavorare sull'argomento, ma il tutto e' immediatamente riportabile a situazioni diverse e piu' complesse
XML Parser 
Per poter manipolare un file XML attraverso Java, sarebbe necessario aprire il file XML e quello DTD (Document Type Definition), attraverso quest'ultimo creare una tabella dei nodi presenti e, una volta creato l'albero, interpretare il file XML per estrarne i dati (ricordiamo che il file DTD è quello che contiene la definizione dei vari elementi/nodi presenti nel file XML). Un vero incubo. Fortunatamente non ci è richiesto questo lavoro perché esistono delle classi che lo fanno per noi. Sono i Parser, classi in grado di interpretare la struttura ad albero del file XML, permettendoci di trattare l'oggetto risultante come qualcosa di più gestibile tramite Java.
In realtà, una volta che il file è stato "digerito" dal parser, avremo un oggetto che avrà una struttura DOM (Document Object Model). La definizione di DOM è più o meno la seguente: DOM è un set di interfacce indipendenti da piattaforma e linguaggio che permette di accedere e modificare la struttura e i dati di un documento XML.DOM è definito dall'onnipresente consorzio W3C.
Tornando ai parser, ne sistono diversi in circolazione. Per citare i più blasonati: IBM XML Parser for Java e Sun ProjectX XML Parser, ma ce ne sono ormai anche di terze parti altrettanto validi. In generale l'utilizzo è molto simile, cambia solo il modo di caricare il file XML. In questo articolo utilizzeremo il parser della Sun.
Quello che faremo è convertire in memoria il contenuto di un documento XML in un oggetto Java. L'esempio è generico e riportabile a qualsiasi tipologia di esigenza.
 
 
 

Conversione di un oggetto XML in 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)> 
  ]>


che corrisponde alla seguente struttura:
 

  MOKABYTE
  | 
  |____ARTICOLO
         |
         |____________TITOLO (testo)
         |
         |____________AUTORE (testo)
         |
         |____________MESE(testo) 

Naturalmente la struttura MOKABYTE può contenere un qualsiasi numero di elementi ARTICOLO.
Usando una terminologia da database, diremmo che la tabella MOKABYTE contiene dei record ARTICOLO costituiti dai campi : TITOLO,AUTORE e MESE. Ed è proprio sfruttando questa impostazione che noi ora convertiremo il file XML in una struttura più manipolabile in Java.
La prima cosa da fare è creare un documento DOM a partire da un file XML. Per fare questo abbiamo bisogno di importare le librerie apposite:
 

  import org.w3c.dom.*;
 import com.sun.xml.tree.*;
 import java.io.*;
il primo import ci mette a disposizione la classe Document, che conterrà il nostro file XML in struttura DOM, dopo che sia stato convertito dal parser. Il tutto avviene così:
try {
    // il path 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 a tutti gli effetti e siamo in grado di estrarne le informazioni presenti Supponiamo che il nostro file XML contenga le seguenti informazioni:
<?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>
 
La struttura è semplice e come vediamo sono presenti 3 "record" di tipo ARTICOLO. Possiamo a questo punto sapere , ad esempio, quanti elementi base del nostro file esistano (ROOT_ELEMENT_TAG, che rappresentano quegli elementi del documento che non abbiano un padre che non sia il documento stesso). Per fare questo ci serviamo del metodo getSize della classe XmlUtils :
  int numeroArticoli=XmlUtils.getSize (doc, ROOT_ELEMENT_TAG );
Ora possiamo estrarre un "record" qualsiasi di quelli esistenti e leggerne i dati, Nel nostro caso avremo un record di tipo "ARTICOLO" del quale potremo conoscere: 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");


In pratica abbiamo estratto il primo elemento del documento avente un tag "primario", cioe' discendente direttamente dal documento stesso e da questo abbiamo potuto ricavare le informazioni in esso contenute. Come si vede tutto il procedimento e' abbastanza semplice. Ora, supponiamo di aver creato un semplice oggetto Java che possa 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;
    }
  }


In realta' si tratta della stessa identica struttura utilizzata nel file XML, solo espressa sotto forma di oggetti Java. Ci bastera' scrivere:
 

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


e il gioco e' fatto. Abbiamo convertito una struttura DOM , e quindi un oggetto XML, in un oggetto Java e da questo momento possiamo manipolarlo a nostro piacimento senza dover piu' interagire con il DOM. In questo modo e' ad esempio possibile, avendo un file XML che contenga la struttura di un elenco di libri, importare i dati convertendoli in corrispondenti oggetti Java e visualizzarli in una griglia della nostra applicazione, consentendone la modifica, per poi ritrasferire il tutto in formato XML, magari pubblicato su web. Vediamo allora il secondo passaggio, cioe' la conversione di una struttura Java in XML.
 

Conversione di un oggetto Java in un oggetto XML

Il passaggio inverso a quello visto in precedenza risulta altrettanto semplice. 
Intanto sappiamo che e' possibile inserire il DTD direttamente nel file XML, senza bisogno di avere due file separati. Per fare la conversione , supponiamo di avere ancora la classe Articolo descritta precedentemente, con in piu' i seguenti metodi:
 
 String getTitolo() {
   return Titolo;
 }
 String getAutore() {
   return Autore;
 }
 String getMese() {
   return Mese;
 }


Questi metodi ci servono per ottenere dall'oggetto Java i dati necessari per popolare il nostro file xml.
Ora possiamo implementare la classe che si occupera' di prendere i dati da un oggetto Articolo che avremo riempito noi con delle informazioni , e di trasformarli in formato XML per metterli nel file apposito. La classe inoltre generera' la porzione DTD. 
 

 // Importiamo al solito le classi per gestire l'input/output,
 // per la gestione del documento in formato DOM
 // e quelle per il parsing del file XML

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

 // La nostra classe

 public class creaXML {
 

   // La stringa che contiene il nome del file XML 

   public static String filexml;
   public static void main (String[] args) {
 

  // L'oggetto Articolo , come lo abbiamo definito in precedenza.
  // E' una classe a parte che rappresenta la struttura in formato
  // oggetto Java del documento XML

  Articolo articolo;

   // Riempiamo noi l'oggetto con dei dati per
   // fare una prova
   //

   articolo.setTitolo("Titolo1");
   articolo.setAutore("Autore1");
   articolo.setMese("Mese");

   try {
    FileOutputStream os= new FileOutputStream(filexml);
    PrintWriter pr=new PrintWriter(os);

    // Dopo aver creato lo stream di scrittura file iniziamo
    // a scriverci dentro.

    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("]>");

    // Dopo aver scritto la parte DTD
    // possiamo cominciare a scrivere
    // il documento XML vero e proprio
    // 
    pr.println("&ltMOKABYTE>");
    pr.println(" &ltARTICOLO>");
    pr.println(" &ltTITOLO>" + articolo.getTitolo() + "</TITOLO>");
    pr.println(" &ltAUTORE>" + articolo.getAutore() + "</AUTORE>");
    pr.println(" &ltMESE> + articolo.getMese() + "</MESE>");
    pr.println(" </ARTICOLO>");
    pr.println("</MOKABYTE>");

    // Ci assicuriamo che il buffer di scrittura sul file
    // venga svuotato, cioe' che tutti i dati immessi nello stream
    // vengano scritti nel file. Poi chiudiamo lo stream.

    pr.flush();
    pr.close();
   } 
   catch ( Exception ex) {

   // Gestione degli errori ridotta all'osso.
   // Si limita a visualizzare l'eventuale errore
   // generato.

    System.out.println(ex);
   }
  }
 } 

Il codice e' ampiamente commentato, per cui penso non ci sia bisogno di dilungarvisi sopra.
Anche in questo caso la procedura utilizzata e' molto semplice. Come abbiamo visto, l'interconversione fra Java e XML e' pressoche' immediata, non richiede manipolazioni complesse e ci permette di far incontrare due realta' tecnologiche di grande attualita'.
 
 
 

Conclusioni 

Abbiamo visto come, con pochissimo codice, sia possibile ottenere la conversione di strutture di dati dal mondo Java a quello XML. Questo fatto e' sintomatico, in quanto in grado di dimostrare la stretta affinita' esistente fra le due tecnologie.Il grande interesse che si e' creato intorno a XML, e il rapido proliferare di tools per l'integrazione fra XML e Java, e' la prova lampante che la cooperazione fra i due e' gia' data come fatto acquisito. In quest'ottica, il tempo utilizzato a sperimentare possibili integrazioni non e' di certo tempo sprecato. Al riguardo potrebbe essere interessante sperimentare l'utilizzo congiunto di Java e PGML (Precision Graphics Markup Language), un linguaggio XML particolarmente votato alla grafica vettoriale 2D su web. Con la stessa logica utilizzata in questo articolo per mappare strutture XML in Java e viceversa, e' infatti possibile mappare strutture grafiche PGML in Java, con tutta una serie di interessanti possibili utilizzi. Come si dice : l'unico limite e' la fantasia.......... 

  
 

MokaByte rivista web su Java

MokaByte ricerca nuovi collaboratori
Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it