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