1. Introdução ao parsing em fluxo
Em Java, historicamente, existem duas abordagens para trabalhar com XML.
Já sabemos que o DOM (Document Object Model) constrói a árvore do documento na memória. É conveniente navegar pelos elementos e editá-los, mas para arquivos grandes isso é caro: a memória acaba rapidamente.
Por sua vez, o SAX (Simple API for XML) processa o arquivo sequencialmente e dispara eventos ao encontrar tags. É econômico em memória, permitindo trabalhar com documentos enormes. Mas escrever handlers é incômodo e não é possível voltar na estrutura.
StAX (Streaming API for XML) surgiu como um compromisso. Ele também é baseado em fluxo, como o SAX, mas dá ao programador mais controle: nós mesmos “puxamos” os eventos do fluxo quando precisamos. Essa abordagem é chamada de pull parsing e permite escrever um código mais claro e flexível.
Introdução ao StAX
StAX (Streaming API for XML) é um parser XML em fluxo moderno para Java, introduzido no JDK 6+.
Ideia principal: pull parsing (parser “puxado”).
Diferente do SAX, em que o parser chama seus métodos por conta própria (modelo push), no StAX você controla o processo:
Você mesmo pede ao parser: “Me dê o próximo evento!”
Analogia:
SAX — é como televisão: os eventos “chegam” até você e você precisa reagir.
StAX — é como um serviço em que você mesmo clica em “próximo vídeo” quando estiver pronto.
Classes‑chave do StAX
Para trabalhar com StAX, você vai precisar de duas classes principais do pacote javax.xml.stream:
- XMLInputFactory — fábrica para criar parsers.
- XMLStreamReader — o parser em fluxo que lê o XML “em pedaços”.
Exemplo básico de código:
import javax.xml.stream.*;
import java.io.FileInputStream;
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new FileInputStream("data.xml"));
while (reader.hasNext()) {
int event = reader.next();
// processamento do evento
}
reader.close();
2. Como o StAX funciona: modelo pull
No StAX você mesmo controla a leitura do XML:
- Abre um stream (por exemplo, um arquivo).
- Cria um XMLStreamReader.
- No loop, chama reader.next() para obter o próximo evento.
- Verifica o tipo do evento (START_ELEMENT, END_ELEMENT, CHARACTERS, etc.).
- Quando chegar ao ponto desejado — processa os dados.
- Fecha o parser.
Esquema de funcionamento:
flowchart TD
A[Abrir XMLStreamReader] --> B{hasNext?}
B -- sim --> C["next()"]
C --> D{Tipo de evento?}
D -- START_ELEMENT --> E[Processar início do elemento]
D -- CHARACTERS --> F[Processar texto]
D -- END_ELEMENT --> G[Processar fim do elemento]
D -- END_DOCUMENT --> H[Finalizar]
B -- não --> H
Qual é a vantagem?
- Você decide quando ler o próximo elemento.
- É possível “parar” no ponto desejado e processar apenas parte do arquivo.
- Não é preciso escrever uma porção de handlers como no SAX.
3. Tipos de eventos no StAX
Quando você chama reader.next(), o parser retorna um tipo de evento — um número inteiro (constante da interface XMLStreamConstants). Aqui estão os principais tipos de eventos:
- START_ELEMENT — início de um elemento XML (<tag>).
- END_ELEMENT — fim de um elemento XML (</tag>).
- CHARACTERS — conteúdo de texto entre tags.
- END_DOCUMENT — fim do documento.
Exemplo de tratamento de eventos:
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
String name = reader.getLocalName();
System.out.println("Início do elemento: " + name);
break;
case XMLStreamConstants.CHARACTERS:
String text = reader.getText().trim();
if (!text.isEmpty()) {
System.out.println("Texto: " + text);
}
break;
case XMLStreamConstants.END_ELEMENT:
System.out.println("Fim do elemento: " + reader.getLocalName());
break;
}
}
4. Nuances úteis
Quando usar StAX?
StAX é a escolha ideal se:
- O arquivo XML é muito grande (gigabytes) e você não quer carregá-lo inteiro na memória.
- É preciso processar apenas parte do documento (por exemplo, encontrar um elemento específico e parar).
- Você quer um código simples e legível: StAX é mais simples que SAX e não exige escrever uma porção de handlers.
Exemplos de tarefas:
- Importar um arquivo XML grande com dados (por exemplo, exportação do 1C, extratos bancários, catálogos de produtos).
- Buscar e processar apenas os elementos necessários (por exemplo, somente <transaction> dentre um milhão de registros).
- Transformar XML “on the fly” (por exemplo, filtragem, agregação).
Comparação: DOM, SAX e StAX
| Abordagem | Memória | Simplicidade | Flexibilidade | Quando usar |
|---|---|---|---|---|
| DOM | Alta (tudo na memória) | Muito simples | Permite alterar a árvore | Arquivos pequenos/médios, quando é preciso editar o XML |
| SAX | Mínima | Complexo (handlers de eventos) | Somente leitura, não é possível voltar | Arquivos muito grandes, processamento simples |
| StAX | Mínima | Média (modelo pull) | Permite ler por partes, fácil pausar | Arquivos grandes, quando você precisa de flexibilidade e simplicidade |
StAX — o meio-termo ideal:
— Não consome memória como o DOM.
— Não exige handlers complexos como o SAX.
— Permite controlar o processo de parsing.
5. Exemplo: lendo um arquivo XML grande com StAX
Suponha que temos o arquivo "books.xml":
<library>
<book>
<title>Java para iniciantes</title>
<author>Ivan Ivanov</author>
</book>
<book>
<title>Java avançado</title>
<author>Pyotr Petrov</author>
</book>
<!-- ... muitos livros ... -->
</library>
Tarefa: imprimir todos os títulos dos livros.
Código com StAX:
import javax.xml.stream.*;
import java.io.*;
public class StaxDemo {
public static void main(String[] args) throws Exception {
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new FileInputStream("books.xml"));
while (reader.hasNext()) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT && "title".equals(reader.getLocalName())) {
reader.next(); // avançar para CHARACTERS
System.out.println("Livro: " + reader.getText());
}
}
reader.close();
}
}
Vantagens:
- Não carregamos o arquivo inteiro na memória.
- É possível processar até um milhão de livros — o programa não vai travar.
6. Erros comuns ao trabalhar com StAX
Erro nº 1: esquecer de fechar o parser ou o stream. Sempre feche o XMLStreamReader e o stream (InputStream) para evitar vazamento de recursos.
Erro nº 2: não verificar o tipo de evento. Nem todo evento é o início ou o fim de um elemento. Verifique o tipo do evento, caso contrário você pode obter strings vazias ou perder dados importantes.
Erro nº 3: ignorar o nível de aninhamento dos elementos. Se a estrutura do XML for complexa (por exemplo, livros dentro de seções), acompanhe o nível atual de aninhamento para não confundir os elementos.
Erro nº 4: usar DOM para arquivos grandes. Se o arquivo for grande, não use DOM, caso contrário você pode obter OutOfMemoryError. Para arquivos grandes — use StAX ou SAX.
Erro nº 5: não tratar exceções. Trabalhar com arquivos e XML pode lançar exceções (XMLStreamException, IOException). Trate-as ou propague-as adequadamente.
GO TO FULL VERSION