Dessa vez trago para vocês um guia rápido com as principais funcionalidades da API Java 1.5 para manipular arquivos XML. Gostaria inicialmente de deixar claro que este tutorial não tem o propósito de ensinar conceitos de XML. Portanto, nos próximos parágrafos estarei assumindo que você já tem conhecimento sobre o referido tópico. Esse artigo é dividido em quatro seções. A primeira mostra um mapeamento entre elementos de um arquivo XML e classes em Java. A segunda ensina como transformar um arquivo XML em disco num objeto de manipulação em Java (parsing). Vamos fazer uma breve explanação sobre os principais métodos de acesso a dados já em memória na seção 3. E, finalmente, iremos mostrar como fazer consulta a documentos XML na seção 4.

Representação de elementos XML

A fim de facilitar o entendimento desta seção, vamos utilizar o documento XML abaixo e ilustrar a partir dele como é feita a representação de cada elemento após ele ser carregado em memória através do parsing (explicado na seção seguinte).

Listagem 1 – Exemplo de um arquivo XML.

<html>

    <head>

                   <title>Título</title>

    </head>



    <body onload="javascript:alert('Olá!')">

                   <p>Olá Mundo!</p>

    </body>

</html>

Todo o documento acima e informações de controle interno como codificação do texto são mapeados e acessados através da interface org.w3c.dom.Document. Ou seja, idealmente após fazer o parsing teremos um objeto que implementa essa interface, que é a visão mais “macro” de um arquivo XML em memória.

Numa visão mais detalhada do arquivo, temos a introdução de conceitos como Node, Element, Attr e Text, todos do pacote org.w3c.dom. Tanto o elemento Document quanto o Element, Attr e Text herdam da interface Node, ou seja, todos esses elementos são vistos como sendo nós da árvore XML.

Parsing

Uma das maneiras de se realizar o parsing de um arquivo XML é através do método parse(File f) da classe javax.xml.parsers.DocumentBuilder. Veja o trecho de código abaixo que mostra como se obter um Document através de um arquivo em disco:

Listagem 2 – Carregando um documento de um arquivo.

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

dbf.setNamespaceAware(false);

DocumentBuilder docBuilder = dbf.newDocumentBuilder();

Document doc = docBuilder.parse(new File("arquivo.xml"));

Para que o parsing suporte namespaces é necessário mudar o valor de false para true na linha em vermelho no código acima. Observe que o conceito e a utilização de namespaces foge ao escopo deste documento.

Agora que estamos com um Document em mãos, vamos mostrar como navegar através dos seus elementos, modificar seu conteúdo e gravá-lo em disco.

Métodos de manipulação de elementos

Além de todos os métodos definidos pela interface Node, a interface Document provê métodos para criação de atributos (Attr), elementos (Element) e textos (Text). Veja um resumo de como fazer isso:

  1. createAttribute(String name) – Cria e retorna um atributo que pode ser inserido em qualquer elemento do tipo Element através do método setAttributeNode(Attr newAttr).
  2. createElement(String tagName) – Cria e retorna um Element que pode ser inserido em outros Elements através do método appendChild(Node newChild) da interface Node.
  3. createTextNode(String data) – Cria e retorna elementos do tipo Text que podem ser inseridos através do mesmo appendChild citado acima em elementos do tipo Element.

A interface Document também possui um método getDocumentElement para obtenção do elemento raiz do XML. Tendo esse elemento do tipo Element em mãos, vamos mostrar um exemplo de código usando o XML da Listagem 1.

Listagem 3 – Código mostrando uso da API.

import java.io.IOException;

import java.io.StringReader;

 

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

 

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

import org.xml.sax.InputSource;

 

import com.sun.org.apache.xml.internal.serialize.OutputFormat;

import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

import com.sun.org.apache.xpath.internal.XPathAPI;

 

public class Exemplo {

 

      public static void main(String[] args) throws Exception {

            DocumentBuilderFactory dbf =

                                DocumentBuilderFactory.newInstance();

            DocumentBuilder docBuilder = dbf.newDocumentBuilder();

            Document doc = docBuilder.parse(new File(“arquivo.xml”));

           

            // mudando o valor de 'title'

            Element htmlTag = doc.getDocumentElement();

            Element headTag =

                       (Element) htmlTag.getElementsByTagName("head").item(0);

            Element titleTag =

                       (Element) headTag.getElementsByTagName("title").item(0);

            titleTag.setTextContent("Novo título");

           

            // adicionando mais parágrafos em 'body'

            Element p1Tag = doc.createElement("p");

            p1Tag.setAttribute("class", "black");

            p1Tag.setTextContent("Um novo parágrafo... ;)");

           

            Element p2Tag = doc.createElement("p");

            p2Tag.setAttribute("class", "white");

            p2Tag.setTextContent("Outro parágrafo..");

           

            Element p3Tag = doc.createElement("p");

            p3Tag.setAttribute("class", "black");

            p3Tag.setTextContent("Fim !");

           

            Element bodyTag =

                        (Element) htmlTag.getElementsByTagName("body").item(0);

            bodyTag.appendChild(p1Tag);

            bodyTag.appendChild(p2Tag);

            bodyTag.appendChild(p3Tag);

           

            // removendo atributo 'onload'

            bodyTag.removeAttribute("onload");

           

            // removendo o primeiro parágrafo de 'body'

            NodeList pTags = bodyTag.getElementsByTagName("p");

            Node p1 = pTags.item(0);

            bodyTag.removeChild(p1);

           

            // fazendo uma consulta XPath

            NodeList resultado = XPathAPI.selectNodeList(bodyTag,

                                                         "p[@class = 'black']");

            for (int i = 0; i < resultado.getLength(); i++) {

                  System.out.println("?: " +

                                     resultado.item(i).getTextContent());

            }

      }

}

Após a execução do exemplo acima, gostaríamos de visualizar como ficou o documento XML final. Podemos fazer isso “serializando” o documento usando um OutputStream (System.out ou até mesmo um FileOutputStream). Veja o exemplo abaixo:

Listagem 4 – Serialização de arquivos XML.

XMLSerializer serializer = new XMLSerializer(System.out, new

   OutputFormat(doc, "iso-8859-1", true));

serializer.serialize(doc);
Consultas a elementos Vamos finalizar este artigo ensinando como usar a org.apache.xpath.XPathAPI para fazer consultas XPath (http://www.w3.org/TR/xpath). Ressalto que não irei focar em como criar a consulta em si, mas sim em como usar a API em sua execução. Para melhor entender sobre XPath.

Alguns dos métodos estáticos disponíveis na XPathAPI são:

  • eval(Node contextNode, String str) Realiza tanto consultas como avalia funções XPath e retornam um objeto org.apache.xpath.objects.XObject que pode encapsular strings, números, listas, entre outros a depender do que for passado no parâmetro str. O contextNode é o nó que informa o ponto inicial da execução de uma busca.
  • selectNodeList(Node contextNode, String str) Realiza consultas XPath e retorna uma lista de elementos XML (Nodes). O contextNode é o nó que informa o ponto inicial da execução de uma busca.
  • selectSingleNode(Node contextNode, String str) Executa a mesma operação do método acima, porém retorna apenas o primeiro Node encontrado.