Lavorare con i file XML in Java utilizzando l'analisi DOM

1. Panoramica

In questo tutorial, discuteremo come analizzare DOM con Apache Xerces, una libreria matura e consolidata per analizzare / manipolare XML.

Sono disponibili più opzioni per analizzare un documento XML; ci concentreremo sull'analisi DOM in questo articolo. Il parser DOM carica un documento e crea un intero albero gerarchico in memoria.

Per una panoramica del supporto delle librerie XML in Java, consulta il nostro articolo precedente.

2. Il nostro documento

Cominciamo con il documento XML che useremo nel nostro esempio:

   Guava Introduction to Guava 04/04/2016 GuavaAuthor  ... 

Nota che il nostro documento ha un nodo radice chiamato "tutorial" con 4 nodi figlio "tutorial". Ognuno di questi ha 2 attributi: "tutId" e "type". Inoltre, ogni "tutorial" ha 4 nodi figli: "titolo", "descrizione", "data" e "autore".

Ora possiamo continuare con l'analisi di questo documento.

3. Caricamento del file XML

Innanzitutto, dobbiamo notare che la libreria Apache Xerces è pacchettizzata con JDK , quindi non abbiamo bisogno di alcuna configurazione aggiuntiva.

Passiamo subito al caricamento del nostro file XML:

DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document doc = builder.parse(new File("src/test/resources/example_jdom.xml")); doc.getDocumentElement().normalize();

Nell'esempio sopra, prima otteniamo un'istanza della classe DocumentBuilder , quindi utilizziamo il metodo parse () sul documento XML per ottenere un oggetto Document che lo rappresenti.

Abbiamo anche bisogno di usare il metodo normalize () per assicurarci che la gerarchia del documento non sia influenzata da spazi bianchi extra o nuove linee all'interno dei nodi.

4. Analisi del DOM

Ora, esploriamo il nostro file XML.

Cominciamo recuperando tutti gli elementi con il tag “tutorial”. Possiamo farlo usando il metodo getElementsByTagName () , che restituirà un NodeList:

@Test public void whenGetElementByTag_thenSuccess() { NodeList nodeList = doc.getElementsByTagName("tutorial"); Node first = nodeList.item(0); assertEquals(4, nodeList.getLength()); assertEquals(Node.ELEMENT_NODE, first.getNodeType()); assertEquals("tutorial", first.getNodeName()); }

È importante notare che Node è il tipo di dati principale per i componenti DOM . Tutti gli elementi, attributi, testo sono considerati nodi.

Successivamente, vediamo come possiamo ottenere gli attributi del primo elemento usando getAttributes () :

@Test public void whenGetFirstElementAttributes_thenSuccess() { Node first = doc.getElementsByTagName("tutorial").item(0); NamedNodeMap attrList = first.getAttributes(); assertEquals(2, attrList.getLength()); assertEquals("tutId", attrList.item(0).getNodeName()); assertEquals("01", attrList.item(0).getNodeValue()); assertEquals("type", attrList.item(1).getNodeName()); assertEquals("java", attrList.item(1).getNodeValue()); }

Qui, otteniamo l' oggetto NamedNodeMap , quindi utilizziamo il metodo item (index) per recuperare ogni nodo.

Per ogni nodo, possiamo usare getNodeName () e getNodeValue () per trovare i loro attributi.

5. Attraversamento dei nodi

Successivamente, vediamo come attraversare i nodi DOM.

Nel seguente test, attraverseremo i nodi figlio del primo elemento e ne stamperemo il contenuto:

@Test public void whenTraverseChildNodes_thenSuccess() { Node first = doc.getElementsByTagName("tutorial").item(0); NodeList nodeList = first.getChildNodes(); int n = nodeList.getLength(); Node current; for (int i=0; i
    

First, we get the NodeList using the getChildNodes() method, then iterate through it, and print the node name and text content.

The output will show the contents of the first “tutorial” element in our document:

title: Guava description: Introduction to Guava date: 04/04/2016 author: GuavaAuthor

6. Modifying the DOM

We can also make changes to the DOM.

As an example, let's change the value of the type attribute from “java” to “other”:

@Test public void whenModifyDocument_thenModified() { NodeList nodeList = doc.getElementsByTagName("tutorial"); Element first = (Element) nodeList.item(0); assertEquals("java", first.getAttribute("type")); first.setAttribute("type", "other"); assertEquals("other", first.getAttribute("type")); }

Here, changing the attribute value is a simple matter of calling an Element‘s setAttribute() method.

7. Creating a New Document

Besides modifying the DOM, we can also create new XML documents from scratch.

Let's first have a look at the file we want to create:

 [email protected] 

Our XML contains a users root node with one user element that also has a child node email.

To achieve this, we first have to call the Builder‘s newDocument() method which returns a Document object.

Then, we'll call the createElement() method of the new object:

@Test public void whenCreateNewDocument_thenCreated() throws Exception { Document newDoc = builder.newDocument(); Element root = newDoc.createElement("users"); newDoc.appendChild(root); Element first = newDoc.createElement("user"); root.appendChild(first); first.setAttribute("id", "1"); Element email = newDoc.createElement("email"); email.appendChild(newDoc.createTextNode("[email protected]")); first.appendChild(email); assertEquals(1, newDoc.getChildNodes().getLength()); assertEquals("users", newDoc.getChildNodes().item(0).getNodeName()); }

To add each element to the DOM, we're also calling the appendChild() method.

8. Saving a Document

After modifying our document or creating one from scratch, we'll need to save it in a file.

We'll start with creating a DOMSource object, then use a simple Transformer to save the document in a file:

private void saveDomToFile(Document document,String fileName) throws Exception { DOMSource dom = new DOMSource(document); Transformer transformer = TransformerFactory.newInstance() .newTransformer(); StreamResult result = new StreamResult(new File(fileName)); transformer.transform(dom, result); }

Similarly, we can print our document in the console:

private void printDom(Document document) throws Exception{ DOMSource dom = new DOMSource(document); Transformer transformer = TransformerFactory.newInstance() .newTransformer(); transformer.transform(dom, new StreamResult(System.out)); }

9. Conclusion

In this quick article, we learned how to use the Xerces DOM parser to create, modify and save an XML document.

As always, the full source code for the examples is available over on GitHub.