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.

 

cod01kxml.JPG

 

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:

fig01kxml.JPG

 

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.