Validating XSD against W3C XML Schema Definition
Asked Answered
J

2

3

I am generating some XML Schemas and would like to ensure that our generator is creating valid XML Schema documents (Not XML). I was trying to come up with the code to validate the XML Schema document, but failing miserably. I didn't think it would be this complex.

  private void validateXsd( String xsdAsString ) {
    try {
      SAXParserFactory factory = SAXParserFactory.newInstance();
      factory.setValidating(true);
      factory.setNamespaceAware(true);
      factory.setFeature( "http://apache.org/xml/features/validation/schema", true );

      SchemaFactory schemaFactory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );

      URL xmlSchemaXSD = this.getClass().getClassLoader().getResource( "com/metamodel/xsd/XMLSchema.xsd" );
      URL xmlSchemaDTD = this.getClass().getClassLoader().getResource( "com/metamodel/xsd/XMLSchema.dtd" );
      URL xmlSchemaDataTypes = this.getClass().getClassLoader().getResource( "com/metamodel/xsd/datatypes.dtd" );

      // requires that XMLSchema.dtd and datatypes.dtd are present in the same directory with the XMLSchema.xsd.
      factory.setSchema( schemaFactory.newSchema( xmlSchemaXSD ) );

      SAXParser parser = factory.newSAXParser();
      // parser.setProperty( "http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema" );

      XMLReader reader = parser.getXMLReader();
      reader.setErrorHandler( new SimpleErrorHandler() );
      reader.parse( new InputSource( IOUtils.toInputStream( xsdAsString ) ) );
    } catch( SAXParseException e ) {
      e.printStackTrace( System.err );
    } catch ( ParserConfigurationException e ) {
      e.printStackTrace( System.err );
    } catch ( SAXException e ) {
      e.printStackTrace( System.err );
    } catch ( IOException e ) {
      e.printStackTrace( System.err );
    }
  }

This code is fairly close to what I need to do, but I'm getting the following errors.

org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'jar:file:/r:/as4ot/lib/metamodel.jar!/com/metamodel/xsd/XMLSchema.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:236)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:172)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:382)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:316)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(XSDHandler.java:2245)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getSchema(XSDHandler.java:1590)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:438)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:556)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:523)
    at com.sun.org.apache.xerces.internal.jaxp.validation.xs.SchemaFactoryImpl.newSchema(SchemaFactoryImpl.java:206)
    at javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:489)
    at javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:521)

I'm using a URL when calling setSchema( uri ) to ensure that XMLSchema.dtd and datatypes.dtd are relative and I hope they are available, but I am unsure how I can check this.

I'm guessing that it doesn't like the fact the XMLSchema.xsd, XMLSchema.dtd and datatypes.dtd are bundled in my jar and hence loaded by the classloader. Is there anyway to solve this so that I can move onto my next hurdle which is org.xml.sax.SAXParseException: src-resolve: Cannot resolve the name 'xml:lang' to a(n) 'attribute declaration' component. assuming that it behaves the same as when I loaded the XMLSchema from a directory path outside of a jar.

My goals are:

  • Load the XMLSchema.xsd from inside the jar so that it is neatly packaged with the code.
  • Get past the next error regarding xml:lang.

Hopefully I'm not asking too much!

Thanks, Stuart

Jabalpur answered 27/7, 2012 at 15:56 Comment(0)
V
3

I wouldn't validate an XSD using the approach you described for a couple of reasons, the most important one being that the XSD as a language is weak so in itself it does not capture the full spec. So, most likely, you may validate something that in fact is not valid.

For XSD validation you have specialized processors; Java has XSOM; follow the user guide.

Vitiate answered 27/7, 2012 at 18:5 Comment(2)
Great, I've given this a go and it worked well. I'd like to fully evaluate the response from Michael before deciding to accept a final answer.Jabalpur
Very simple in the end: XSOMParser parser = new XSOMParser(); parser.setErrorHandler( .. ); parser.parse( IOUtils.toInputStream( xsdAsString ) ); although I had to ensure that I used xsom14.jar as I'm on an older JRE. I'm using relaxngDatatype-2.2.jar with it. Thanks for the help!Jabalpur
S
2

I agree with Petru that validating a schema against the schema for schema documents is not a very useful thing to do, because it won't detect all errors in your schema. The only real way to ensure that your schema is valid is to pass it to a schema processor.

For example, with Saxon

Processor p = new Processor(true);
StreamSource ss = new StreamSource(new File('mySchema.xsd');
p.getSchemaManager().load(ss);

will tell you whether your schema is valid or not.

Shiprigged answered 27/7, 2012 at 22:3 Comment(3)
Thanks, although I have tried this approach and I keep finding a NullPointerException on the p.getSchemaManager() as it returns null. I'm using saxon9he.jar and also tried setting licenced edition to false when creating the Processor object, it did not help.Jabalpur
For schema processing in Saxon, you need to get Saxon-EE.Shiprigged
I'm going to head for the XSOM route as I'm not looking to make a purchase. Thanks very much for the help, it's appreciated!Jabalpur

© 2022 - 2024 — McMap. All rights reserved.