validar con java xsd xerces

java - Validar un archivo XML contra mĂșltiples definiciones de esquema



validar xml con xsd (6)

Estoy tratando de validar un archivo XML contra varios esquemas diferentes (disculpas por el ejemplo inventado):

  • a.xsd
  • b.xsd
  • c.xsd

c.xsd, en particular, las importaciones b.xsd y b.xsd importan a.xsd, usando:

<xs:include schemaLocation="b.xsd"/>

Estoy tratando de hacer esto a través de Xerces de la siguiente manera:

XMLSchemaFactory xmlSchemaFactory = new XMLSchemaFactory(); Schema schema = xmlSchemaFactory.newSchema(new StreamSource[] { new StreamSource(this.getClass().getResourceAsStream("a.xsd"), "a.xsd"), new StreamSource(this.getClass().getResourceAsStream("b.xsd"), "b.xsd"), new StreamSource(this.getClass().getResourceAsStream("c.xsd"), "c.xsd")}); Validator validator = schema.newValidator(); validator.validate(new StreamSource(new StringReader(xmlContent)));

pero esto no está logrando importar los tres esquemas correctamente, lo que resulta en que no se puede resolver el nombre ''blah'' en un componente (n) ''grupo''.

Validé esto con éxito usando Python , pero teniendo problemas reales con Java 6.0 y Xerces 2.8.1 . ¿Alguien puede sugerir qué está pasando mal aquí, o un enfoque más fácil para validar mis documentos XML?


De la documentación de xerces: http://xerces.apache.org/xerces2-j/faq-xs.html

import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; ... StreamSource[] schemaDocuments = /* created by your application */; Source instanceDocument = /* created by your application */; SchemaFactory sf = SchemaFactory.newInstance( "http://www.w3.org/XML/XMLSchema/v1.1"); Schema s = sf.newSchema(schemaDocuments); Validator v = s.newValidator(); v.validate(instanceDocument);


El material de esquema en Xerces es (a) muy, muy pedante, y (b) da mensajes de error completamente inútiles cuando no le gusta lo que encuentra. Es una combinación frustrante.

Las cosas del esquema en Python pueden ser mucho más indulgentes, y dejaron pasar pequeños errores en el esquema no reportados.

Ahora bien, si, como dices, c.xsd incluye b.xsd y b.xsd incluye a.xsd, entonces no hay necesidad de cargar los tres en la fábrica de esquemas. No solo es innecesario, probablemente confundirá a Xerces y generará errores, por lo que este puede ser su problema. Simplemente pase c.xsd a la fábrica y deje que resuelva b.xsd y a.xsd, lo que debería hacer en relación con c.xsd.


Enfrenté el mismo problema y después de investigar encontré esta solución. Esto funciona para mi.

Enum para configurar los diferentes XSDs :

public enum XsdFile { // @formatter:off A("a.xsd"), B("b.xsd"), C("c.xsd"); // @formatter:on private final String value; private XsdFile(String value) { this.value = value; } public String getValue() { return this.value; } }

Método para validar:

public static void validateXmlAgainstManyXsds() { final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); String xmlFile; xmlFile = "example.xml"; // Use of Enum class in order to get the different XSDs Source[] sources = new Source[XsdFile.class.getEnumConstants().length]; for (XsdFile xsdFile : XsdFile.class.getEnumConstants()) { sources[xsdFile.ordinal()] = new StreamSource(xsdFile.getValue()); } try { final Schema schema = schemaFactory.newSchema(sources); final Validator validator = schema.newValidator(); System.out.println("Validating " + xmlFile + " against XSDs " + Arrays.toString(sources)); validator.validate(new StreamSource(new File(xmlFile))); } catch (Exception exception) { System.out.println("ERROR: Unable to validate " + xmlFile + " against XSDs " + Arrays.toString(sources) + " - " + exception); } System.out.println("Validation process completed."); }


Entonces, en caso de que alguien más se encuentre con el mismo problema aquí, necesité cargar un esquema primario (y esquemas secundarios implícitos) a partir de una prueba unitaria, como recurso, para validar una Cadena XML. Usé Xerces XMLSchemFactory para hacer esto junto con el validador de Java 6.

Para cargar el esquema del niño correctamente a través de una inclusión, tuve que escribir una resolución de recursos personalizada. El código se puede encontrar aquí:

https://code.google.com/p/xmlsanity/source/browse/src/com/arc90/xmlsanity/validation/ResourceResolver.java

Para usar el resolver, especifíquelo en la fábrica del esquema:

xmlSchemaFactory.setResourceResolver(new ResourceResolver());

y lo usará para resolver tus recursos a través del classpath (en mi caso desde src / main / resources). Cualquier comentario es bienvenido en esto ...


Terminé usando esto:

import org.apache.xerces.parsers.SAXParser; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; import java.io.IOException; . . . try { SAXParser parser = new SAXParser(); parser.setFeature("http://xml.org/sax/features/validation", true); parser.setFeature("http://apache.org/xml/features/validation/schema", true); parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true); parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", "http://your_url_schema_location"); Validator handler = new Validator(); parser.setErrorHandler(handler); parser.parse("file:///" + "/home/user/myfile.xml"); } catch (SAXException e) { e.printStackTrace(); } catch (IOException ex) { e.printStackTrace(); } class Validator extends DefaultHandler { public boolean validationError = false; public SAXParseException saxParseException = null; public void error(SAXParseException exception) throws SAXException { validationError = true; saxParseException = exception; } public void fatalError(SAXParseException exception) throws SAXException { validationError = true; saxParseException = exception; } public void warning(SAXParseException exception) throws SAXException { } }

Recuerde cambiar:

1) El parámetro "http: // your_url_schema_location" para la ubicación del archivo xsd.

2) La cadena "/home/user/myfile.xml" para la que apunta a su archivo xml.

No tuve que establecer la variable: -Djavax.xml.validation.SchemaFactory:http://www.w3.org/2001/XMLSchema=org.apache.xerces.jaxp.validation.XMLSchemaFactory


http://www.kdgregory.com/index.php?page=xml.parsing sección '' Esquemas múltiples para un solo documento ''

Mi solución basada en ese documento:

URL xsdUrlA = this.getClass().getResource("a.xsd"); URL xsdUrlB = this.getClass().getResource("b.xsd"); URL xsdUrlC = this.getClass().getResource("c.xsd"); SchemaFactory schemaFactory = schemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); //--- String W3C_XSD_TOP_ELEMENT = "<?xml version=/"1.0/" encoding=/"UTF-8/" standalone=/"yes/"?>/n" + "<xs:schema xmlns:xs=/"http://www.w3.org/2001/XMLSchema/" elementFormDefault=/"qualified/">/n" + "<xs:include schemaLocation=/"" +xsdUrlA.getPath() +"/"/>/n" + "<xs:include schemaLocation=/"" +xsdUrlB.getPath() +"/"/>/n" + "<xs:include schemaLocation=/"" +xsdUrlC.getPath() +"/"/>/n" +"</xs:schema>"; Schema schema = schemaFactory.newSchema(new StreamSource(new StringReader(W3C_XSD_TOP_ELEMENT), "xsdTop"));