Como reutilizar um DocumentBuilder?

0 respostas
M

Boa tarde Pessoal.

Estou tentando desenvolver um pequeno aplicativo para realizar a validação de arquivos XML que recebemos na empresa. Esta validação se resume em realizar o parse do XML, validando-o contra o seu Schema.

Como temos um volume grande de arquivos, o quesito "Performance" é fundamental. Para isso, imaginei criar uma método simples que retornasse um DocumentBuilder contendo todas as configurações de validação e schemas. Esse método seria executado apenas uma vez e o resultado do mesmo seria utilizado para parsear os arquivos.

Segue o código para facilitar:

package br.org.metrus.xml;

import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;

public class ValidadorTISS {

    public static final String ANS_XML_SCHEMA_V2 = "http://www.ans.gov.br/padroes/tiss/schemas/old/tissV2_01_02.xsd";
    public static final String ANS_XML_SCHEMA_V3 = "http://www.ans.gov.br/padroes/tiss/schemas/tissV2_01_03.xsd";

    private DocumentBuilder parser = null;

    public ValidadorTISS(String[] schemas) {
        parser = this.getDOMParser(schemas);
    }

    public boolean validaArquivo(File arquivo) {

        /* tentativa de reaproveitar o parser */
        parser.reset();

        parser.setErrorHandler(new MyErrorHandler());

        boolean valido = true;

        try {
            parser.parse(arquivo);
        } catch (SAXException e) {
            System.out.println(arquivo.getName() + ";" + e.getMessage());
            valido = false;
        } catch (IOException e) {
            e.printStackTrace();
            valido = false;
        }

        return valido;

    }

    private DocumentBuilder getDOMParser(final String[] schemas ) {

        try {

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

            String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
            String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";

            String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";

            factory.setValidating(true);
            factory.setNamespaceAware(true);
            factory.setIgnoringComments(true);

            factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
            factory.setAttribute(JAXP_SCHEMA_SOURCE, schemas);

            // Criar o parser
            parser = factory.newDocumentBuilder();


        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }

        return parser;
    }
}

O sistema realiza corretamente a validação do primeiro arquivo, porém, para os demais arquivos o sistema lança um erro: [i]cvc-elt.1: Cannot find the declaration of element.

Tenho a impressão que o parse realizado "navega" pela árvore do Schema, validando o arquivo. Porém, ao iniciar a validação do próximo arquivo, acredito que a posição da validação anterior é mantida, o que impede a validação do outro arquivo. (Isso foi a minha interpretação do erro).

Se eu altero o código (conforme abaixo) o sistema funciona corretamente, mas o processo se torna lento:

...

    private DocumentBuilder parser = null;

    private String[] schemas = null;

    public ValidadorTISS(String[] schemas) {
        this.schemas = schemas;
    }

    public boolean validaArquivo(File arquivo) {

        parser = this.getDOMParser(schemas);

        parser.setErrorHandler(new MyErrorHandler());

        ...

Notem que nesta nova versão, a cada arquivo a ser validado, eu sou obrigado a criar um novo DocumentBuilder...

Então, eis a questão: Como reutilizar um DocumentBuilder?

Obrigado!

Criado 3 de dezembro de 2008
Respostas 0
Participantes 1