Lugar para compartir información interesante con mis amigos.

Saturday, July 08, 2023

Cómo Validar un XML con múltiples XSD precargados como byte []

 El problema

Tengo varios XSD que dependen unos de otros y debo validar un XML con ellos. Para ejecutar esa operación rápidamente y evitar la carga de disco duro cada vez que voy a ejecutar esa transacción, voy a tener los XSD en memoria como arreglos de bytes.

SchemaFactory schemaFactory = SchemaFactory.
        newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source [] sources=schemas.toArray(new Source[schemas.size()]);
Schema schema = schemaFactory.newSchema(sources);



En teoría este código funciona para cargar todos los esquemas, pero estoy obteniendo esta excepción, a pesar de tener todas las definiciones en los esquemas:

org.xml.sax.SAXParseException; lineNumber: 27; columnNumber: 85; src-resolve: Cannot resolve the name 'cac:CountryType' to a(n) 'type definition' component.

Para verificar que todo esté bien con los esquemas, simplemente se cargaron como archivos y todo funcionó bien. Entonces, ¿qué hacer?

La Solución


Se implementó un ResourceResolver personalizado ByteArrayResourceResolver, que se establece al ShemaFactory así: 

schemaFactory.setResourceResolver(
    new ByteArrayResourceResolver(scheme.getXsdBytes())
);

En el constructor se envía un Map con el nombre de cada archivo y su contenido como arreglo de bytes. La implementación es la siguiente:

public class ByteArrayResourceResolver implements LSResourceResolver {
private final Map<String, byte[]> resources;

public ByteArrayResourceResolver(Map resources) {
this.resources = resources;
}

@Override
public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
LSInput input =new Input();
ByteArrayInputStream bis=new ByteArrayInputStream(resources.get(systemId));
input.setByteStream(bis);
input.setBaseURI(baseURI);
input.setPublicId(publicId);
input.setSystemId(systemId);
return input;
}
}

Finalmente Input es una implementación con getters y setters de LSImput.

El error se genera porque baseURI llega en null para algunos de los schemas. (la investigación de la causa quedará pendiente )




0 comments:

Popular Posts

Pedro Rozo. Powered by Blogger.