Manipulando arquivos XML em Java com a API DOM - Parte III

18 May 2009
3 mins read

No post Manipulando arquivos XML em Java com a API DOM - Parte II vimos como fazer a leitura de um arquivo XML utilizando a API DOM presente no java (a partir versão 1.4). Neste post (último sobre a API DOM) vamos ver como editar um arquivo XML após tê-lo na árvore DOM.

Às vezes precisamos editar alguma informação do XML, modificar alguma informação, ou adicionar, ou até mesmo excluir algum dado do XML.

Vamos utilizar o XML abaixo como exemplo de arquivo inicial. O arquivo está nomeado como "contatos.xml":

contatos_xml

Antes de começarmos a modificar o XML, temos que ter o arquivo na árvore DOM, para isso, vamos carregar o arquivo na memória:

[code lang="java"]
//fazer o parse do arquivo e criar o documento XML
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse("contato.xml");
[/code]

Após carregar o arquivo, vamos chegar no nó que desejamos modificar. Vamos aproveitar e imprimir as informações no console para verificação:

[code lang="java"]
//Passo 1: obter o elemento raiz
Element raiz = doc.getDocumentElement();

//Passo 2: localizar os elementos filhos da agenda
NodeList listaContatos = raiz.getElementsByTagName("contato");

//Passo 3: obter os elementos de cada elemento contato
for (int i=0; i<listaContatos.getLength(); i++){

//como cada elemento do NodeList é um nó, precisamos fazer o cast
Element elementoContato = (Element) listaContatos.item(i);

//cria um objeto Contato com as informações do elemento contato
Contato contato = criaContato(elementoContato);
System.out.println(contato);
[/code]

Se um contato já estiver gravado (atributo gravado="SIM"), então vamos removê-lo do arquivo. Para isso, utilizamos o método removeChild(Node noASerRemovido). Se o contato ainda não estiver gravado, vamos modificar o atributo para "SIM":

[code lang="java"]
//remove o elemento do XML se contato já está gravado
//caso contrário, marca como gravado
if (contato.isGravado()){
raiz.removeChild(elementoContato);
i--; //atualiza, já que alterou o lenght
} else{
elementoContato.setAttribute("gravado", "SIM");
}
[/code]

Vamos agora substituir o telefone do contato de id="03". Para isso, vamos criar um novo Elemento telefone (lembrando que também temos que cria um Nó de texto para relacionar ao elemento Telefone (pode relembrar como é árvore DOM aqui)). Após criar o novo elemento telefone, vamos subtituir o novo elmento pelo elemento que já existe; para isso, utilizamos o método replaceChild(Node novoNo, Node antigoNo):

[code lang="java"]
//subtitui o telefone do Pedro da Silva
if (contato.getId() == 3){
Element tel = doc.createElement("telefone");
tel.appendChild(doc.createTextNode("11 99999999"));
Node telefone = elementoContato.getElementsByTagName("telefone").item(0);
elementoContato.replaceChild(tel, telefone);
}
[/code]

Vamos agora adicionar um novo elemento contato ao elmento raiz agenda. Para isso, vamos seguir a lógica da criação do elemento telefone. Passos a seguir:

  1. Criação do elemento contato
  2. Setar os atributos do elmento contato
  3. Criar o elemento nome + criar o TextNode (valor) do elemento nome
  4. Criar o elemento endereco + criar o TextNode (valor) do elemento endereco
  5. Criar o elemento telefone + criar o TextNode (valor) do elemento telefone
  6. Criar o elemento email + criar o TextNode (valor) do elemento email
  7. Adicionar o elementos nome, endereco, telefone e email ao elemento contato

Lembrar que a ordem em que os elementos são inseridos é muito importate!
Para facilitar e poder reusar o código futuramente, vamos criar um método que faça isso:

[code lang="java"]
public Element criaElementoAPartirContato(Contato contato){
//cria um elemento contato
Element element = doc.createElement("contato");

//cria o atributo id e gravado
element.setAttribute("id", "04");
element.setAttribute("gravado", "SIM");

//cria os elementos
Element nome = criaElementoGenerico("nome", contato.getNome());
Element endereco = criaElementoGenerico("endereco", contato.getEndereco());
Element telefone = criaElementoGenerico("telefone", contato.getTelefone());
Element email = criaElementoGenerico("email", contato.getEmail());

//adiciona os elementos ao contato
element.appendChild(nome);
element.appendChild(endereco);
element.appendChild(telefone);
element.appendChild(email);

return element;
}
[/code]

Vamos utilizar o método no código principal, adicionando o elmento criado ao elemento raiz:

[code lang="java"]
//Cria um novo elemento
Element novoContato = criaElementoAPartirContato(criaContatoFicticio());
//adiciona um novo elemento no XML
raiz.appendChild(novoContato);
[/code]

Bem, já vimos como remover, modificar e adicionar elementos ao XML. Agora falta apenas gravar o arquivo modificado em algum lugar!
Se desejar, pode criar uma classe para montar o XML na mão, ou seja, montar as tags, identação, etc. Mas tem que tomar muito cuidado quando for fazer isso, pois pode acabar modificando a estrutura na serialização (sem querer), e o XML pode ficar inválido.

Uma maneira que muitos desenvolvedores utilizam é criar uma transformação identidade, ou seja, é uma transformação XSL sem folha de estilo.
Você cria uma origem (documento DOM) e um destino (arquivo XML), e aplica a transformação sem folha de estilo.

[code lang="java"]
//grava o documento XML editado
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new FileOutputStream("contato_modificado.xml"));
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
transformer.transform(source, result);
[/code]

Após rodar o programa, vamos ter o seguinte XML modificado:

contatos_mod_xml

O código completo desse post você pode fazer o download aqui (projeto no formato da IDE Eclipse)
download

Até a próxima!