Manipulando Arquivo XML Parte I: API Nativa
Este tutorial é a primeira parte de uma série de tutoriais que farei sobre arquivos XML e Java. Neste tutorial vou exemplificar como manipular arquivos XML com as API’s nativas do JDK. Veremos como criar um arquivo XML e como ler este arquivo. Deste modo não precisaremos adicionar ao projeto bibliotecas externas do Java Development Kit (JDK).
1. Salvar arquivo
Antes de tudo, precisamos após criar o objeto XML salvá-lo em um arquivo. Vamos então criar um metodo para isso. Crie uma classe MainTest
e em seguida crie o metodo salvarArquivo(String documento)
. Já irei informar neste primeiro passo todos os imports necessários.
import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.File; import java.io.FileOutputStream; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collection; public class MainTest { private static File file = new File("C:\\TutorialArquivos\\Contatos.xml"); private static void salvarArquivo(String documento) throws Exception { FileOutputStream fos = new FileOutputStream(file, true); fos.write(documento.getBytes()); fos.flush(); fos.close(); } }
2. Criando as classes Contato, Endereço e Telefone
Vamos utilizar três classes para manipular os dados que serão inseridos no XML. Nosso arquivo ficara com a estrutura do XML da figura 1.
Crie a classe Telefone
, Endereco
e Contato
conforme a listagem 2.
public class Telefone { private int id; private int ddd; private int numero; //gere os metodos getters and setters //gere o metodo toString() } public class Endereco { private int id; private String logradouro; private String bairro; private String cep; private String cidade; private String complemento; private int numero; //gere os metodos getters and setters //gere o metodo toString() } public class Contato { private int id; private String nome; private String email; private Endereco endereco; private Collectiontelefones = new ArrayList (); //gere os metodos getters and setters //gere o metodo toString() }
Como devem ter visto na Figura 1, teremos mais de um telefone no arquivo, então é por este motivo que foi criada uma coleção de telefones na classe Contato
. Enquanto isso terá apenas um endereço no arquivo, por este motivo teremos um objeto Endereco
na classe Contato
.
3. metodo gerarXML e converter
Vamos criar um metodo chamado converter()
que irá transformar o objeto Document
em uma String
para que possamos salvar no arquivo o XML através da classe FileoutputStream
.
private static String converter(Document document) throws TransformerException { //Criamos uma instancia de Transformer //O metodo setOutputProperty cria a formatacao //ou nao do XML no arquivo. Se 'yes' entao formata, //se 'no' entao escreve o arquivo em uma unica linha Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //inicializar StreamResult para gravar para String StreamResult result = new StreamResult(new StringWriter()); DOMSource source = new DOMSource(document); transformer.transform(source, result); //Recupera o conteudo em formato String String xmlString = result.getWriter().toString(); //Exibe o resultado da transformacao System.out.append(xmlString); //devolve a string return xmlString; }
Agora vamos criar o metodo que irá gerar o XML, é neste metodo que criaremos as tags do XML e iremos inserir nelas os valores que posteriormente criaremos. Leia os comentários no código para entender o que acontece passo a passo na geração do XML.
private static void gerarXml(Contato contato) throws Exception { //Criamos um nova instancia de DocumentBuilderFactory DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); //Usamos o metodo newDocumentBuilder() para //criar um nova instancia de DocumentBuilder DocumentBuilder db = dbf.newDocumentBuilder(); //Obtem uma nova instancia de um Document //objeto para construir uma arvore com Document. Document doc = db.newDocument(); //Cria a tag raiz do XML Contato Element tagContato = doc.createElement("Contato"); Element idContato = doc.createElement("id"); Element nomeContato = doc.createElement("nome"); Element emailContato = doc.createElement("email"); //Insere os valores nas tags de contato idContato.setTextContent(String.valueOf(contato.getId())); nomeContato.setTextContent(contato.getNome()); emailContato.setTextContent(contato.getEmail()); //Insere na tag Contato as tags id, nome e email tagContato.appendChild(idContato); tagContato.appendChild(nomeContato); tagContato.appendChild(emailContato); //Cria a tag Telefones Element tagFones = doc.createElement("Telefones"); //Cria a tag filha Telefone Element tagFone = null; //Cria as tags de Telefone Element idFone; Element dddFone; Element numeroFone; //Inserir a lista de telefones for (Telefone fone : contato.getTelefones()) { tagFone = doc.createElement("Telefone"); idFone = doc.createElement("id"); dddFone = doc.createElement("ddd"); numeroFone = doc.createElement("numero"); //Insere os valores de telefones nas tags referentes idFone.setTextContent(String.valueOf(fone.getId())); dddFone.setTextContent(String.valueOf(fone.getDdd())); numeroFone.setTextContent(String.valueOf(fone.getNumero())); //Insere as tags Telefone na tag Telefone tagFone.appendChild(idFone); tagFone.appendChild(dddFone); tagFone.appendChild(numeroFone); //Insere a tag Telefone na tag pai Telefones tagFones.appendChild(tagFone); } //Inserer a tag telefones na tag Contato tagContato.appendChild(tagFones); //Cria a tag Endereco Element tagEndereco = doc.createElement("Endereco"); //Cria as tags de Endereco Element idEnd = doc.createElement("id"); Element logradouroEnd = doc.createElement("logradouro"); Element bairroEnd = doc.createElement("bairro"); Element cepEnd = doc.createElement("cep"); Element cidadeEnd = doc.createElement("cidade"); Element complementoEnd = doc.createElement("complemento"); Element numeroEnd = doc.createElement("numero"); //Inserer os dados na nas tags de Endereco idEnd.setTextContent(String.valueOf(contato.getEndereco().getId())); logradouroEnd.setTextContent(contato.getEndereco().getLogradouro()); bairroEnd.setTextContent(contato.getEndereco().getBairro()); cepEnd.setTextContent(contato.getEndereco().getCep()); cidadeEnd.setTextContent(contato.getEndereco().getCidade()); complementoEnd.setTextContent(contato.getEndereco().getComplemento()); numeroEnd.setTextContent(String.valueOf(contato.getEndereco().getNumero())); //Insere as tags de Endereco na tag Endereco tagEndereco.appendChild(idEnd); tagEndereco.appendChild(logradouroEnd); tagEndereco.appendChild(bairroEnd); tagEndereco.appendChild(cepEnd); tagEndereco.appendChild(cidadeEnd); tagEndereco.appendChild(complementoEnd); tagEndereco.appendChild(numeroEnd); //Insere a tag Endereco na tag Contato tagContato.appendChild(tagEndereco); //Insere a tag Contato com as demais tags no objeto Document doc doc.appendChild(tagContato); //vamos converter o objeto doc //em String para salvar no arquivo String arquivo = converter(doc); //vamos agora salvar o arquivo xml salvarArquivo(arquivo); }
4. metodo main
Agora iremos criar o metodo main para criar o objeto Contato
e passá-lo por par metro por uma chamada ao metodo gerarXml()
.
public static void main(String[] args) { Telefone residencial = new Telefone(); residencial.setId(1); residencial.setDdd(55); residencial.setNumero(32214512); Telefone celular = new Telefone(); celular.setId(2); celular.setDdd(55); celular.setNumero(99879885); Collectiontelefones = new ArrayList (); telefones.add(residencial); telefones.add(celular); Endereco endereco = new Endereco(); endereco.setId(11); endereco.setLogradouro("Rua dos Javanezes"); endereco.setBairro("Largo Zero"); endereco.setCep("97010600"); endereco.setCidade("Java City"); endereco.setNumero(65); endereco.setComplemento("Ap.103A"); Contato contato = new Contato(); contato.setId(100); contato.setNome("Fulano da Silva"); contato.setEmail("fulano@email.com"); contato.setEndereco(endereco); contato.setTelefones(telefones); try { gerarXml(contato); //Contato c = lerXml(); //System.out.println(c.toString()); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (TransformerException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }
Agora que criamos este metodo vamos executá-lo para gerar o arquivo XML.
5. metodo getChildTagValue
Esse metodo vai nos facilitar o parser do arquivo XML quando formos ler os dados contidos nele. Ele possui dois parametros, o Element
será a tag pai que será lida e o parametro String
será a tag que contém o valor que será lido.
public static String getChildTagValue(Element elem, String tagName) throws Exception { NodeList children = elem.getElementsByTagName(tagName); String result = null; //children, a tag pai que estamos lendo, // por exemplo a tagif (children == null) { return result; } //child, a tag que queremos recuperar o valor, por exemplo //a tag Element child = (Element) children.item(0); if (child == null) { return result; } //recuperamos o texto contido na tagName result = child.getTextContent(); return result; }
6. metodo lerXml
Vamos agora criar o metodo que irá ler e preencher o objeto Contato
para podermos exibir o resultado da leitura do arquivo. Leia os comentários contidos no código fonte para entender passo a passo o que é necessário fazer para ler o arquivo.
private static Contato lerXml() throws Exception, SAXException, TransformerException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); //Informamos qual arquivo xml vamos ler Document doc = db.parse(new InputSource(file.toString())); //Criamos um objeto Element que vai receber as informacoes de doc Element raiz = doc.getDocumentElement(); //Vamos criar um objeto Endereco Endereco endereco = new Endereco(); //Informamos qual tag vamos ler NodeList endList = raiz.getElementsByTagName("Endereco"); Element endElement = (Element) endList.item(0); //Passamos para o metodo getChildTagValue a tag Pai que //iremos ler mais qual tag Filha será capturada endereco.setId(Integer.parseInt(getChildTagValue(endElement, "id"))); endereco.setNumero(Integer.parseInt(getChildTagValue(endElement, "numero"))); endereco.setBairro(getChildTagValue(endElement, "bairro")); endereco.setCep(getChildTagValue(endElement, "cep")); endereco.setCidade(getChildTagValue(endElement, "cidade")); endereco.setComplemento(getChildTagValue(endElement, "complemento")); endereco.setLogradouro(getChildTagValue(endElement, "logradouro")); //Vamos criar uma colecao de Telefones ja que // temos mais de um Telefone a capturar Collectiontelefones = new ArrayList (); NodeList fonesList = raiz.getElementsByTagName("Telefone"); Element foneElement; //Fazemos um for nas tags Telefone e adicionamos os dados // em um objeto Telefone e depois na colecao for (int i = 0; i < fonesList.getLength(); i++) { foneElement = (Element) fonesList.item(i); Telefone telefone = new Telefone(); telefone.setId(Integer.parseInt(getChildTagValue(foneElement, "id"))); telefone.setDdd(Integer.parseInt(getChildTagValue(foneElement, "ddd"))); telefone.setNumero(Integer.parseInt(getChildTagValue(foneElement, "numero"))); //Adicionamos a coleção as tags Telefone telefones.add(telefone); } //Agora iremos ler os dados de Contato //Como esses dados estao apenas dentro // da tag Contato e de mais nenhuma outra // vamos entao usar o elemento raiz Contato contato = new Contato(); contato.setId(Integer.parseInt(getChildTagValue(raiz, "id"))); contato.setNome(getChildTagValue(raiz, "nome")); contato.setEmail(getChildTagValue(raiz, "email")); //Agora vamos inserir em contato os objetos telefones e endereco contato.setEndereco(endereco); contato.setTelefones(telefones); return contato; }
Agora comente no metodo main a chamada ao metodo gerarXml()
e descomente as duas linhas seguintes e execute o programa, será exibido no console a recuperação dos dados através do objeto Contato c
.
Conclusão
Vimos então como criar as tags XML e como inserir valores nelas, também vimos como recuperar essas informações de um arquivo. Não utilizamos neste tutorial nenhuma biblioteca externa às existentes no JDK, no próximo tutorial, a parte 2 irá exemplificar como utilizar a biblioteca externa JDOM, que facilita um pouco mais a criação e leitura de um arquivo XML.
Saiba mais
- Documentação das classes do pacote org.xml.sax
- Documentação das classes do pacote java.io
- Documentação das classes do pacote org.w3c.dom
- Documentação das classes do pacote javax.xml.parsers
- Documentação das classes do pacote javax.xml.transform
- Documentação da classe javax.xml.transform.dom.DOMSource
- Documentação da classe javax.xml.transform.stream.StreamResult
- Documentação das classes do pacote java.util