|
|
Guilherme Silveira
Aqui você vai aprender a navagar por um arquivo XML através do SAX, que faz o parsing de um XML por eventos.
Download do material relacionado ao tutorial
Arquivos Xml e Sax
Este tutorial visa ensinar a usar a api chamada de SAX, Simple Api for XML, que vem junto com o Java 1.4 e, portanto, você deve ter esta versão do SDK instalado.
Percorrida estas páginas, voce será capaz ler um arquivo XML e usar os dados que lhe interessa. É necessário que você saiba o que é XML e para que você vai utilizá-lo.
SAX e suas implementações: SAX é um conjunto de interfaces (uma api) que deve ser implementada para efetuar o parsing de arquivos xml. No momento o Java 1.4 ja vem com implementações da api SAX. Você pode encontrar, por exemplo, o Xerces e o Crimson do projeto jakarta e instalá-los separadamente caso possua uma versão anterior do java, porém precisará adaptar um pouco mais o código, que vai alem do objetivo desse tutorial.
O Parser
Para criar um objeto parser, utilizamos uma API da Sun que procura um parser adequado.
1 // cria a factory e o parser
2 SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
Então abrimos o arquivo XML para leitura:
1 // abre a conexao com o arquivo, buffer de 1 mega
2 InputSource input = new InputSource(arquivo);
|
Uma vez que a API do Sax é orientada a eventos, criamos um objeto que lida com os eventos e dizemos ao parser para utilizar esse Handler durante o parsing do arquivo xml.
1 // inicia o parsing
2 parser.parse(input, new XMLHandler());
|
Observação: caso você queira utilizar um parser de XML que monte uma árvore com todo o XML, você deve usar um parser do tipo DOM. Lembre-se que o DOM coloca tudo em memória, o que pode não ser eficiente para XMLs grandes (em business to business, XMLs chegam a 500 megabytes).
Agora falta criar a nossa classe XMLHandler. Ela vai recebendo chamadas de método a medida que o arquivo XML é parseado pelo SAXParser.
XMLHandler
As classes que lidam com os eventos da api do SAX devem extender a DefaultHandler.
Quem já trabalhou com apis de GUI tanto em C/C++, Visual Basic ou Java (swing/awt), sabe como uma API orientada a eventos funciona e tera mais facilidade para entender o funcionamento dessa classe que criaremos. Durante o parsing do XML, esta nossa classe receberá chamadas, de acordo com o que o parser encontrar!
A classe DefaultHandler tem os métodos startDocument, endDocument, startElement, endElement e characters sendo chamadas quando um documento comeca e termina, quando um elemento (tag) comeca e termina e quando algum texto eh encontrado em um elemento (tag).
Nota: O estranho, e o que torna a api do SAX rápida, é que o método characters pode ser chamado mais de uma vez pra mesma TAG. Isso acontece, por exemplo, quando o arquivo xml possui código unicode.
Devido a esse detalhe do método characters devemos entao manter uma variável local a classe, que se preenche a cada chamada deste método, e é liberada no momento que o método endElement eh chamado, daremos o nome de valorAtual a ela.
Temos também que manter uma variável com o "endereço" atual do parser na estrutura do arquivo XML, isto é, quando o arquivo estiver dentro da tag Compra->Produtos->Produto devemos saber que ele esta nesse tag, e não no Venda->Produtos->Produto. Portanto não adianta checarmos se uma tag possui o nome que desejamos, mas precisamos sim é checar se o "endereço" atual no arquivo xml é o que procuramos. Para isso criamos a variável galhoAtual contendo o galho de parsing atual.
1 class XMLHandler extends DefaultHandler {
2
3 /** o galho atual */
4 private StringBuffer galhoAtual = new StringBuffer(200);
5
6 /** o valor da tag atual */
7 private StringBuffer valorAtual = new StringBuffer(100);
8
9 }
|
Então implementamos os métodos que serão chamados no começo e fim do documento:
1 /** comeca um documento novo */
2 public void startDocument() {
3 System.out.print("iniciando");
4 }
5
6 /** termina o documento */
7 public void endDocument() {
8 System.out.print("\nterminando");
9 }
|
Dica: Neste momento você pode finalizar algum processo com os dados que processou do arquivo inteiro.
Parseando as tags
Agora implementamos o método que marca o início de uma nova Tag, primeiro setando o galhoAtual para seu novo valor e limpando o valorAtual.
Então imprimimos o nome do galho atual para ter alguma saáda do programa.
01 /** comeca uma tag nova */
02 public void startElement(
03 String uri,
04 String localName,
05 String tag,
06 Attributes atributos)
07 throws ParserException {
08
09 // seta o galho atual
10 galhoAtual.append("/" + tag);
11
12 // mostra a tag
13 System.out.print(
14 "\n<"
15 + galhoAtual.substring(1)
16 + (atributos.getLength() != 0 ? " +ATRIBUTOS" : "")
17 + ">");
18
19 // limpa a tag atual
20 valorAtual.delete(0, valorAtual.length());
21
22 }
|
E o método que trata o fim de uma Tag, onde mostramos o valor interno da Tag, limpamos ele e setamos o galhoAtual novamente.
01 /** termina uma tag */
02 public void endElement(String uri, String localName, String tag)
03 throws ParserException {
04
05 // mostra o valor
06 System.out.print(valorAtual.toString().trim());
07 // e limpa
08 valorAtual.delete(0, valorAtual.length());
09
10 // seta o galho atual
11 galhoAtual.delete(
12 galhoAtual.length() - tag.length() - 1,
13 galhoAtual.length());
14
15 }
|
Por fim precisamos implementar o método que trata os valores internos das Tags, que adiciona esse valor para o valorAtual, uma vez que essa função pode ser chamada infinitas vezes dentro de uma tag.
Isto é, se você tem um XML deste tipo:
Pode ser (não necessariamente), que você receba duas chamadas para o characters(): uma para "gui", e outra para " lherme", por exemplo. Isto acontece devido a otimização da API.
Dica: A utilização de um StringBuffer é sempre melhor, uma vez que buffers trabalham muito mais rápido que Strings.
1 /** recebe os dados de uma tag */
2 public void characters(char[] ch, int start, int length) {
3
4 // adiciona ao valor atual
5 valorAtual.append(ch, start, length);
6
7 }
|
O arquivo java que acompanha o tutorial pode ser compilado e rodado assim:
java ExemploSax arquivo.xml
|
Utilize-o para ver realmente como o SAX funciona. Dentro do .zip tem 2 arquivos XML de exemplo.
|
|
|