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:
[code]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;
}
}
[/code]
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:
[code] …
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());
...
[/code]
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!