Analisando um arquivo XML usando o analisador SAX

Analisando um arquivo XML usando o analisador SAX

1. Visão geral

SAX, também conhecido comothe Simple API for XML, é usado para analisar documentos XML.

Neste tutorial, aprenderemos o que é SAX e por que, quando e como deve ser usado.

2. SAX: a API simples para XML

O SAX é uma API usada para analisar documentos XML. Éis based on events gerado durante a leitura do documento. Os métodos de retorno de chamada recebem esses eventos. Um manipulador personalizado contém esses métodos de retorno de chamada.

A API é eficiente porque descarta eventos logo após os retornos de chamada os receberem. Portanto,SAX has efficient memory management, ao contrário do DOM, por exemplo.

3. SAX vs DOM

DOM significa Document Object Model. ODOM parser does not rely on events. Além disso, ele carrega todo o documento XML na memória para analisá-lo. O SAX é mais eficiente em termos de memória que o DOM.

O DOM também tem seus benefícios. Por exemplo, o DOM suporta XPath. Também torna mais fácil operar em toda a árvore do documento de uma vez desdethe document is loaded into memory.

4. SAX vs StAX

O StAX é mais recente que o SAX e o DOM. SignificaStreaming API for XML.

A principal diferença com SAX é queStAX uses a pull mechanism em vez do mecanismo de push de SAX (usando callbacks). Isso significa que o controle é dado ao cliente para decidir quando os eventos precisam ser puxados. Portanto, não há obrigação de extrair todo o documento se apenas uma parte dele for necessária.

Ele fornece uma API fácil para trabalhar com XML com uma maneira de analisar com eficiência de memória.

Ao contrário do SAX, ele não fornece validação de esquema como um de seus recursos.

5. Analisando o arquivo XML usando um manipulador personalizado

Vamos agora usar o seguinte XML representando o site de exemplo e seus artigos:


    
        
Parsing an XML File Using SAX Parser SAX Parser's Lorem ipsum...
Parsing an XML File Using DOM Parser DOM Parser's Lorem ipsum...
Parsing an XML File Using StAX Parser StAX's Lorem ipsum...

Começaremos criando POJOs para nosso elemento raizexample e seus filhos:

public class example {
    private List articleList;
    // usual getters and setters
}
public class exampleArticle {
    private String title;
    private String content;
    // usual getters and setters
}

Continuaremos criando oexampleHandler. Esta classe implementará os métodos de retorno de chamada necessários para capturar os eventos.

Substituiremos quatro métodos da pesquisa da superclasseDefaultHandler, que caracteriza um evento:

    • characters(char[], int, int) recebe caracteres com limites. Vamos convertê-los emStringe armazená-los em uma variável deexampleHandler

    • startDocument() é invocado quando a análise começa - vamos usá-lo para construir nossa instânciaexample

    • startElement() é invocado quando a análise começa para um elemento - vamos usá-lo para construir instânciasList<exampleArticle> ouexampleArticle -qName nos ajuda a fazer a distinção entre os dois tipos

    • endElement() é invocado quando a análise termina para um elemento - é quando vamos atribuir o conteúdo das tags às suas respectivas variáveis

Com todos os callbacks definidos, podemos agora escrever a classeexampleHandler:

public class exampleHandler extends DefaultHandler {
    private static final String ARTICLES = "articles";
    private static final String ARTICLE = "article";
    private static final String TITLE = "title";
    private static final String CONTENT = "content";

    private example website;
    private String elementValue;

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        elementValue = new String(ch, start, length);
    }

    @Override
    public void startDocument() throws SAXException {
        website = new example();
    }

    @Override
    public void startElement(String uri, String lName, String qName, Attributes attr) throws SAXException {
        switch (qName) {
            case ARTICLES:
                website.articleList = new ArrayList<>();
                break;
            case ARTICLE:
                website.articleList.add(new exampleArticle());
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        switch (qName) {
            case TITLE:
                latestArticle().title = elementValue;
                break;
            case CONTENT:
                latestArticle().content = elementValue;
                break;
        }
    }

    private exampleArticle latestArticle() {
        List articleList = website.articleList;
        int latestArticleIndex = articleList.size() - 1;
        return articleList.get(latestArticleIndex);
    }

    public example getWebsite() {
        return website;
    }
}

Constantes de string também foram adicionadas para aumentar a legibilidade. Um método para recuperar o artigo mais recente encontrado também é conveniente. Finalmente, precisamos de um getter para o objetoexample.

Observe que o acima não é thread-safe, já que estamos mantendo o estado entre as chamadas de método.

6. Testando o analisador

Para testar o analisador, instanciaremosSaxFactory,SaxParsereexampleHandler:

SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
SaxParserMain.exampleHandler exampleHandler = new SaxParserMain.exampleHandler();

Depois disso, analisaremos o arquivo XML e afirmaremos que o objeto contém todos os elementos esperados analisados:

saxParser.parse("src/test/resources/sax/example.xml", exampleHandler);

SaxParserMain.example result = exampleHandler.getWebsite();

assertNotNull(result);
List articles = result.getArticleList();

assertNotNull(articles);
assertEquals(3, articles.size());

SaxParserMain.exampleArticle articleOne = articles.get(0);
assertEquals("Parsing an XML File Using SAX Parser", articleOne.getTitle());
assertEquals("SAX Parser's Lorem ipsum...", articleOne.getContent());

SaxParserMain.exampleArticle articleTwo = articles.get(1);
assertEquals("Parsing an XML File Using DOM Parser", articleTwo.getTitle());
assertEquals("DOM Parser's Lorem ipsum...", articleTwo.getContent());

SaxParserMain.exampleArticle articleThree = articles.get(2);
assertEquals("Parsing an XML File Using StAX Parser", articleThree.getTitle());
assertEquals("StAX Parser's Lorem ipsum...", articleThree.getContent());

Como esperado, oexample foi analisado corretamente e contém os subobjetos esperados.

7. Conclusão

Acabamos de descobrir como usar o SAX para analisar arquivos XML. É uma API poderosa que gera uma pegada leve de memória em nossos aplicativos.

Como de costume, o código deste artigo está disponívelover on GitHub.