Esse artigo faz parte da revista Java Magazine edição 22. Clique aqui para ler todos os artigos desta edição

img

Atenção: por essa edição ser muito antiga não há arquivo PDF para download.Os artigos dessa edição estão disponíveis somente através do formato HTML. 

Byte Code

XML Turbinado com Java

Explore a STaX, JAXB e outras APIs XML

Conheça e compare técnicas modernas de processamento de XML com Java, incluindo binding, parsing e serialização de JavaBeans

Osvaldo Pinali Doederlein

A manipulação de arquivos XML tornou-se parte rotineira do desenvolvimento de praticamente qualquer espécie de aplicação. Essa tecnologia supre desde necessidades triviais, como substituir os velhos arquivos “properties” por formatos estruturados e validáveis até as mais avançadas, como construir websites ultra-complexos, gerar relatórios com saídas em vários formatos (como HTML, PDF ou XLS), ou servir de base a um novo middleware, os web services.

Em todos esses casos, a tarefa essencial é processar arquivos XML. Na base da pilha de tecnologias de suporte a XML, encontramos os parsers, que dão suporte a todos os componentes de mais alto nível – de facilidades genéricas de tratamento de XML como transformação XSL, a tecnologias mais complexas e especializadas como SOAP ou os descritores do J2EE. Uma falha ou problema de desempenho no parsing de XML irá produzir uma falha ou problema de desempenho em todas as camadas superiores desta arquitetura. Por isso é essencial que a etapa de parsing seja executada de forma robusta e eficiente.

Este artigo faz uma revisão das APIs de parsing de XML, sem tentar aprofundar-se em nenhuma delas: cada uma seria material suficiente para um artigo inteiro, e a JavaMagazine já cobriu o assunto, por exemplo na Edições 2 (Processando XML com Java) e na Edição 9 (em vários artigos). Meu objetivo principal é apresentar as APIs mais recentes – a JAXB, StAX e Serialização XML de JavaBeans – que ainda são menos conhecidas e utilizadas. Além disso, faço um paralelo entre as várias opções, discutindo diferenças de desempenho, estilo e facilidade de programação.

Todo código do artigo é compatível com o J2SE 1.4, sendo que os exemplos de StAX e JAXB necessitam do Java Web Services Developer Pack (JWSDP) versão 1.5.

A evolução do XML

O parsing básico de XML ainda não é um problema completamente resolvido, embora estejamos próximos disso. O padrão XML 1.0 (do W3C) foi publicado em 1998 e atualizado em fevereiro de 2004 com melhorias de pouca monta no suporte a Unicode e normalização. Há poucos padrões tão importantes e tão estáveis; esta estabilidade tem sido essencial ao sucesso do XML. Outros padrões associados são um pouco mais recentes: XPath 1.0 (novembro/1999), XML Schema 1.0 (maio/2001), XSL (outubro/2001). Há novas versões dessas especificações em andamento, mas sem nada de revolucionário.

Os padrões XML já entraram em “modo legado”. A tecnologia é tão amplamente utilizada, que ninguém tem pressa de inventar nada radicalmente novo, nem é louco de quebrar compatibilidade com o que já exista. É suficiente observar a lentidão glacial que tem sido a transição do padrão de validação de documentos de DTD para XML Schema. Muitos padrões “de aplicação” só recentemente estão migrando para Schemas. Por exemplo, o JavaServer Faces, apesar de bastante recente, irá introduzir suporte a Schemas apenas na versão 1.2, que ainda está em definição. E mesmo assim continuará suportando DTDs para quem não tiver pressa de adotar a novidade. Não deixa de ser surpreendente, considerando que o XML Schema está disponível e é bem suportado há anos por diversos parsers. A JAXB, uma das APIs que veremos aqui, foi pioneira em exigir o uso de XSD, mas somente por absoluta necessidade. Como de costume o peso do legado é o preço do sucesso rápido.

No universo Java a principal implementação dos padrões fundamentais de XML é sem dúvida o parser Xerces (que implementa os padrões XML 1.1, Namespaces 1.1, DOM Level2, SAX 2.0.1, Schema 1.0, JAXP 1.2), além do Xalan (que implementa XSL 1.0, XPath 1.0). Ambos são projetos da Apache Software Foundation. Esses parsers costumavam ser atualizados de poucos em poucos meses, mas desde fevereiro de 2004, com o Xerces 2.6.2 e Xalan 2.6.0, não houve mais nenhum release. Isso não significa que os desenvolvedores tenham abandonado os projetos: é apenas um sinal do grau de maturidade dos padrões e suas implementações. O Xerces 2.7.0 está em desenvolvimento e irá suportar SAX 2.0.2, DOM Level3, XML Schema 1.1, XInclude 1.0 e JAXP 1.3, além de outras melhorias menores.

Parsing de XML em Java

Para testar as diversas APIs de parsing, vamos criar um documento XML bastante simples (mostrado na Listagem 1), que poderia ser usado para armazenar o sumário da Java Magazine, tal como aparece em javamagazine.com.br/edicoes/jm19 (veja a Figura 1). O documento utiliza alguns recursos essenciais de XML: tags aninhadas, atributos e texto interno. Para testar os parsers, vamos utilizar as classes Edicao e Secao, que encapsulam cada elemento deste arquivo (veja a Listagem 2).

img

Figura 1. Página de resumo da Edição 19 da Java Magazine: inspiração para o exemplo de XML

 Listagem 1. Documento XML de teste

<?xml version="1.0"?>

<Edicao>

  <Secao nome="Editorial" autor="Leonardo Galvão">

    Na Edição 19 conheça os mecanismos do Struts para

    criar a camada de visualização de suas aplicações com

    ActionForms, DynaActionForms e validação...

  </Secao>

 

  <Secao nome="A Vida, o Universo e Tudo Mais"

         titulo=" A Luta pelo Java Livre" autor="Bruno Souza">

     Com o Tiger solto, como está sendo tratada uma das

     questões mais controversas da tecnologia Java?

  </Secao>

 

  <Secao nome="Byte Code" titulo="Matemática em Java"

         autor="Osvaldo Pinali Doederlein">

    Entenda e explore os recursos de matemática da J2SE,

    tanto em ponto flutuante como números decimais

  </Secao>

</Edicao>

 

Listagem 2. Mapeamento Java do documento XML

Edicao.java

 

import java.io.Serializable;

import java.util.ArrayList;

import java.util.List;

 

public class Edicao implements Serializable {

  private List secoes = new ArrayList();

 

  public List getSecoes () { return secoes; }

 

  public void setSecoes (List<Secao> secoes) {

    this.secoes = secoes;

  }

 

  public void addSecao (Secao secao) {

    this.secoes.add(secao);

  }

 

  public String toString () {

    StringBuffer s = new StringBuffer();

    for (int i = 0; i < secoes.size(); ++i)

      s.append(secoes.get(i));

    return s.toString();

  }

}

 

Secao.java

import java.io.Serializable;

 

public class Secao implements Serializable {

  private String nome;

  private String autor;

  private String texto;

  public Secao () {}

 

  public Secao (final String nome, final String autor,

      final String texto)

  {

    this.nome = nome; this.autor = autor; this.texto = texto;

  }

 

  public String getAutor () { return autor;  }

  public void setAutor (String autor) { this.autor = autor; }

  public String getNome () { return nome; }

  public void setNome (String nome) { this.nome = nome; }

  public String getTexto () { return texto; }

  public void setTexto (String texto) { this.texto = texto; }


  public String toString () {

    return "nome=" + nome + ",autor=" + autor + "\n" + texto;

  }

}

Parsing com DOM

O DOM (Document Object Model, parte da JSR-5: JAXP – Java API for XML Parsing) é o mapeamento para Java do padrão DOM Level 1 do W3C. O DOM é centrado em um modelo orientado a objetos representando o documento XML; o parser transforma o documento numa árvore de “nós” (nodes) que reproduz a estrutura de itens do documento.

No documento de exemplo a raiz desta árvore é o Node do elemento <Edicao>, que possui uma NodeList contendo três nós para cada seção; as seções de texto interno a elementos são objetos TextNode. Podemos ver na Listagem 3 que o DOM permite escrever código razoavelmente compacto. Mas a API deixa a desejar, pois foge completamente das normas de design de APIs do Java. Por exemplo, NodeList é uma coleção totalmente ad hoc, não sendo compatível com java.util.List ou com qualquer interface padrão de coleções do Java. Além disso define métodos estranhos, como getLength() ao invés de length() ou size(), e item() no lugar de get(). Essa esquisitice ocorre porque o DOM é um padrão do W3C que pretende definir uma API independente de linguagem de programação, tanto que as classes e interfaces ficam em pacotes org.w3c.*.

 

Listagem 3. Parser DOM

import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

 

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

import org.xml.sax.InputSource;

...

Quer ler esse conteúdo completo? Tenha acesso completo