Java DOM Parser - Parsing di un file XML

Il parsing di documenti XML è un’operazione molto diffusa e utile. In Java esistono sostanzialmente due approcci: DOM e SAX. Mentre SAX (leggi qui) si basa sulla generazione di eventi quando si verificano determinate situazioni (es. inizio del documento, inizio di un elemento, fine di un elemento...) e non mantiene in memoria il documento, con DOM tutto l'albero del documento viene caricato in memoria e possiamo lavorare su di esso come meglio preferiamo. Appare subito evidente che SAX utilizza al meglio le risorse (DOM soffre con documenti XML molto grandi), ma non consente di navigare il documento al contrario né di modificare o creare documenti XML.

Con DOM, ogni elemento del documento XML diventa un nodo dell'albero rappresentato da una classe che implementa l'interfaccia org.w3c.dom.Node. Questa interfaccia rappresenta un singolo nodo nell’albero del documento e fornisce metodi per esplorare o modificare l'albero e per conoscere le proprietà di ogni nodo.

I punti principali da seguire per elaborare un documento XML con DOM sono:

Ad esempio, l’interfaccia Document (sotto-intefaccia di Node) ci mette a disposizione i seguenti metodi:

L'interfaccia Node, invece, ci offre:

I tipi di nodo sono costanti dell'interfaccia Node:

Node.ATTRIBUTE_NODE
Node.ELEMENT_NODE
Node.COMMENT_NODE
Node.DOCUMENT_FRAGMENT_NODE
Node.DOCUMENT_NODE
Node.DOCUMENT_TYPE_NODE
Node.CDATA_SECTION_NODE
Node.TEXT_NODE
Node.ENTITY_NODE
Node.ENTITY_REFERENCE_NODE
Node.NOTATION_NODE
Node.PROCESSING_INSTRUCTION_NODE

Per quanto riguarda l’interfaccia NodeList, questa offre I metodi:

Il codice seguente mostra come è possibile analizzare con DOM un documento XML (il cui percorso è passato come parametro della riga di comando) e stamparne le informazioni principali.


public class DocumentDomCleanParser{
	
       //main
       public static void main(String[] args) {
             String filename = args[1];
             DocumentDomCleanParser ddp = new DocumentDomCleanParser();
             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 
             try {
                    DocumentBuilder builder = dbf.newDocumentBuilder();
                    File xmlFile = new File(filename);
                    Document document = builder.parse(xmlFile);
                    ddp.printNodeInfo(document);
             } catch (SAXException sxe) {
                    Exception  x = sxe;
                    if (sxe.getException() != null)
                           x = sxe.getException();
                    x.printStackTrace();
             } catch (ParserConfigurationException pce) {
                    pce.printStackTrace();
             } catch (IOException ioe) {
                    ioe.printStackTrace();
             }
 
       }
	   
       /**
        * Stampa le info sui nodi, in modo ricorsivo
        * @param currentNode il nodo corrente
        */
       public void printNodeInfo(Node currentNode) {
             short sNodeType = currentNode.getNodeType();
             //Se è di tipo Element ricavo le informazioni e le stampo
             if (sNodeType == Node.ELEMENT_NODE) {
                    String sNodeName = currentNode.getNodeName();
                    String sNodeValue = searchTextInElement(currentNode);
                    NamedNodeMap nnmAttributes = currentNode.getAttributes();
                    System.out.println("Elemento: " + sNodeName);
                    System.out.println("Attributi: " +
                                 printAttributes(nnmAttributes));
                    if (!sNodeValue.trim().equalsIgnoreCase("")) {
                           System.out.println("Contenuto: " + sNodeValue);
                    }
                    System.out.print("\n");
             }
             int iChildNumber = currentNode.getChildNodes().getLength();
             //Se non si tratta di una foglia continua l'esplorazione
             if (currentNode.hasChildNodes()) {
                    NodeList nlChilds = currentNode.getChildNodes();
                    for (int iChild = 0; iChild < iChildNumber; iChild++) {
                           printNodeInfo(nlChilds.item(iChild));
                    }
             }
       }
	   
       /*
        * Ricerca di testo in un dato nodo
        */
       private static String searchTextInElement(Node elementNode) {
             String sText = "";
             if (elementNode.hasChildNodes()) {
                    //Il child node di tipo testo è il primo
                    Node nTextChild = elementNode.getChildNodes().item(0);
                    sText = nTextChild.getNodeValue();
             }
             return sText;
       }
 
       private static String printAttributes(NamedNodeMap nnm) {
             String sAttrList = new String();
             if (nnm != null && nnm.getLength() > 0) {
                    for (int iAttr=0; iAttr < nnm.getLength(); iAttr++) {
                           sAttrList += nnm.item(iAttr).getNodeName();
                           sAttrList += "=";
                           sAttrList += nnm.item(iAttr).getNodeValue();
                           sAttrList += "; ";
                    }
                    return sAttrList;
             }
             else {
                    return "assenti";
             }
       }
}