Trabalhando com arquivos XML em Java usando a análise DOM

Trabalhando com arquivos XML em Java usando a análise DOM

1. Visão geral

Neste tutorial, discutiremos como analisar DOM comApache Xerces - uma biblioteca madura e estabelecida para análise / manipulação de XML.

Existem várias opções para analisar um documento XML; vamos nos concentrar na análise DOM neste artigo. O analisador DOM carrega um documento e cria uma árvore hierárquica inteira na memória.

Para uma visão geral do suporte a bibliotecas XML em Java, verifique nossoarticle anterior.

2. Nosso Documento

Vamos começar com o documento XML que usaremos em nosso exemplo:



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

Observe que nosso documento possui um nó raiz chamado "tutoriais" com 4 nós filhos "tutoriais". Cada um destes possui 2 atributos: "tutId" e "type". Além disso, cada "tutorial" possui 4 nós filhos: "título", "descrição", "data" e "autor".

Agora podemos continuar analisando este documento.

3. Carregando arquivo XML

Primeiro, devemos observar quethe Apache Xerces library is packaged with the JDK, portanto, não precisamos de nenhuma configuração adicional.

Vamos pular direto para o carregamento de nosso arquivo XML:

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

No exemplo acima, primeiro obtemos uma instância da classeDocumentBuilder e, em seguida, usamos o métodoparse() no documento XML para obter um objetoDocument que a representa.

Também precisamos usar o métodonormalize() para garantir que a hierarquia do documento não seja afetada por quaisquer espaços em branco extras ou novas linhas nos nós.

4. Analisando o DOM

Agora, vamos explorar nosso arquivo XML.

Vamos começar recuperando todos os elementos com a tag “tutorial”. Podemos fazer isso usando o métodogetElementsByTagName(), que retornará umNodeList:

@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 observar queNode is the primary datatype for the DOM components. Todos os elementos, atributos, texto são considerados nós.

A seguir, vamos ver como podemos obter os atributos do primeiro elemento usandogetAttributes():

@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());
}

Aqui, obtemos o objetoNamedNodeMap e usamos o métodoitem(index) para recuperar cada nó.

Para cada nó, podemos usargetNodeName()egetNodeValue() para encontrar seus atributos.

5. Nós transversais

A seguir, vamos ver como atravessar os nós DOM.

No teste a seguir, vamos percorrer os nós filho do primeiro elemento e imprimir seu conteúdo:

@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

Primeiro, obtemosNodeList usando o métodogetChildNodes(), em seguida, iteramos por meio dele e imprimimos o nome do nó e o conteúdo do texto.

A saída mostrará o conteúdo do primeiro elemento "tutorial" em nosso documento:

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

6. Modificando o DOM

Também podemos fazer alterações no DOM.

Como exemplo, vamos mudar o valor do atributotype de “java” para “outro”:

@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"));
}

Aqui, alterar o valor do atributo é uma simples questão de chamar um métodoElement'ssetAttribute().

7. Criando um Novo Documento

Além de modificar o DOM, também podemos criar novos documentos XML do zero.

Vamos primeiro dar uma olhada no arquivo que queremos criar:



    
        [email protected]
    

Nosso XML contém um nó raizusers com um elementouser que também possui um nó filhoemail.

Para conseguir isso, primeiro temos que chamar o métodoBuilder'snewDocument(), que retorna um objetoDocument.

Em seguida, chamaremos o métodocreateElement() do novo objeto:

@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());
}

Para adicionar cada elemento ao DOM, também estamos chamando o métodoappendChild().

8. Salvando um Documento

Depois de modificar nosso documento ou criar um do zero, precisaremos salvá-lo em um arquivo.

Começaremos criando um objetoDOMSource e, em seguida, usaremos umTransformer simples para salvar o documento em um arquivo:

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);
}

Da mesma forma, podemos imprimir nosso documento no 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. Conclusão

Neste artigo rápido, aprendemos como usar o analisador DOM do Xerces para criar, modificar e salvar um documento XML.

Como sempre, o código-fonte completo dos exemplos está disponívelover on GitHub.