kXML - Fazendo parser de um XML com J2ME
O kXML é um parser de XML estável e otimizado, para ser utilizado em pequenos dispositivos com recursos limitados de memória e processamento, e desta forma sendo ideal para ser utilizado com J2ME.
Existem algumas técnicas conhecidas para realizar o parser de um XML. Uma das mais utilizadas é o DOM, que utiliza um modelo baseado em árvore, criando uma estrutura de dados na memória, onde é possível acessar essa estrutura através de um conjunto de objetos. O DOM é muito simples de utilizar, mas sendo que muitos objetos são armazenados em memória, ele não é recomendado para ser utilizado com J2ME.
Outra técnica conhecida é chamada de “push parser”, que é orientada a eventos, onde ao ler um XML, um objeto “listener” é notificado sempre que novas tags são encontradas. Esta forma é como o popular SAX trabalha.
O kXML utiliza um outro modelo, conhecido como “pull parser”, onde uma pequena quantidade de dados é analisada de cada vez. A aplicação faz o parser do XML solicitando sempre a próxima parte que deve ser processada, isto geralmente é feito em um loop até o fim do XML. Desta forma, a aplicação pode exibir as informações do XML a medida que o parser é efetuado, como por exemplo, ao fazer um download de um arquivo do servidor. Já um parser que utiliza DOM, precisaria ler o documento inteiro para montar uma estrutura de árvores, para somente depois exibir as informações.
Fazendo o download
A versão utilizada neste artigo é a 2.2.2:
http://prdownloads.sourceforge.net/kxml/kxml2-min-2.2.2.jar?download
Exemplo do arquivo XML
Neste artigo vamos criar um simples Midlet, que vai fazer o parser do arquivo XML abaixo, e exibirá os dados na tela.
Código fonte do Midlet
O código fonte do Midlet é muito simples. O código abre uma InputStream para o XML exibido anteriormente, que é utilizada para criar uma instância de org.kxml2.io.KXmlParser.
Os métodos require() e nextTag() são utilizados para percorrer o XML. O método nextTag() obviamente retorna a próxima tag e o método require() obriga o parser a posicionar o “cursor” na posição desejada. A medida que o parser é realizado, os dados das pessoas existentes são exibidas na tela do dispositivo.
package javamagazine;
import …
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class XMLParserMidlet extends MIDlet {
Form form = new Form("Pessoas");
protected void startApp() throws MIDletStateChangeException {
InputStream in = getClass().getResourceAsStream("pessoas.xml");
try {
Display.getDisplay(this).setCurrent(form);
parser(in);
} catch (Exception e) {
e.printStackTrace();
}
}
private void parser(InputStream in) throws Exception {
//Inicia o XMLParser
KXmlParser parser = new KXmlParser();
parser.setInput(new InputStreamReader(in));
parser.nextTag();
//Posiciona na tag <agenda>
parser.require(XmlPullParser.START_TAG, null, "agenda");
//Enquanto é diferente de END_TAG
while (parser.nextTag () != XmlPullParser.END_TAG)
{
//Posiciona na tag <pessoa>
parser.require(XmlPullParser.START_TAG, null, "pessoa");
parserPessoa(parser);
form.append("\n");
parser.require(XmlPullParser.END_TAG, null, "pessoa");
}
parser.require(XmlPullParser.END_TAG, null, "agenda");
parser.next();
parser.require(XmlPullParser.END_DOCUMENT, null, null);
}
private void parserPessoa(KXmlParser parser) throws Exception {
//Enquanto é diferente de </pessoa>
while (parser.nextTag() != XmlPullParser.END_TAG) {
//Posiciona em uma tag "START". Ex: <nome> ou <fone>
parser.require(XmlPullParser.START_TAG, null, null);
String name = parser.getName();
String text = parser.nextText();
System.out.println("Tag: " + name + " -> " + text);
//Adiciona o texto no Form
form.append(text);
//Posiciona no fim da tag </nome> ou </fone>
parser.require(XmlPullParser.END_TAG, null, name);
}
}
pauseApp…
destroyApp…
}
Ao executar o exemplo, a seguinte tela vai aparecer:
Entendendo o exemplo
O código abre uma InputStream utilizando o método getResourceAsStream(), mas em uma aplicação real provavelmente o XML seria obtido através de uma conexão Http ou um socket:
InputStream in = getClass().getResourceAsStream("pessoas.xml");
Depois de abrir uma InputStream, pode-se criar uma instância da classe KXmlParser conforme mostrado abaixo:
InputStream in = ….
KXmlParser parser = new KXmlParser();
parser.setInput(new InputStreamReader(in));
O próximo passo é chamar o método require() para posicionar o parser na tag desejada, neste caso: <agenda>.
parser.require(XmlPullParser.START_TAG, null, "agenda");
Para ler todas as pessoas, o método require(“pessoa”) é chamado sucessivamente para buscar a próxima tag <pessoa> que deve ser processada, até encontrar o fim da tag </agenda>.
while (parser.nextTag () != XmlPullParser.END_TAG)
{
//Posiciona na tag <pessoa>
parser.require(XmlPullParser.START_TAG, null, "pessoa");
parserPessoa(parser);
form.append("\n");
parser.require(XmlPullParser.END_TAG, null, "pessoa");
}
Para cada tag <pessoa> encontrada, o método parserPessoa(parser) é chamado para ler os seus elementos.
Note que dentro do loop, o método “parser.require(XmlPullParser.START_TAG, null, null);” é chamado para posicionar o cursor na próxima tag <nome> ou <fone>, para posteriormente obter o conteúdo deste elemento utilizando o método parser.nextText().
private void parserPessoa(KXmlParser parser) throws Exception {
//Enquanto é diferente de </pessoa>
while (parser.nextTag() != XmlPullParser.END_TAG) {
//Posiciona em uma tag "START". Ex: <nome> ou <fone>
parser.require(XmlPullParser.START_TAG, null, null);
String text = parser.nextText();
form.append(text);
//Posiciona no fim da tag </nome> ou </fone>
parser.require(XmlPullParser.END_TAG, null, name);
}
}
Conclusão
Neste artigo foi demonstrado como fazer um parser de um XML, utilizando o kXML, uma API simples e otimizada, ideal para ser utilizada com J2ME.
Espero que tenham gostado e até a próxima.