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:
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
void parse(File f)
void parse(String uri)
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";
}
}
}