In Hibernate there is a particular branch of logic where we need to parse and validate an org.xml.sax.InputSource that might represent either a Hibernate mapping (hbm.xml) file, a 1.0-compliant orm.xml file or a 2.0-compliant orm.xml file. Now currently Hibernate mapping files are defined by a DTD and both versions of the orm.xml files by an XSD. Currently the code builds a SAXReader with DTD and Schema validation enabled and tries to read in the source. It first maps Schema validation to the 2.0 version of the XSD; if an error occurs it then tries re-parsing mapping Schema validation to 1.0 version of the XSD.
Now I am not an XML guru, but this seemed wasteful to me. But try as I could I could not find a way to say that we need to resolve the XSD to one file (locally) if the root element defined version=2.0
as an attribute versus another if it defined version=1.0
. Really I guess its a matter of conditionally resolving the schemaLocation. Anyone know if this is possible?
My next thought was to leverage the javax.xml.validation.Validator contract added in JDK 1.5. So basically, I would enabled DTD validation of the document during parse and simply parse the document initially. Then I peeked at the root element to see if the document was a Hibernate mapping or an orm.xml. If an orm.xml, I then check its version attribute, load a Validator based on the proper XSD and do a Validator.validate( new DOMSource(...) ). First, due to the separate parse and then validate steps, just how much slower will this be?
Also, I had a very irksome issue with this approach anyway. In my tests I created a document that is valid according to the 2.0 schema, but I identified the version as 1.0
and used the 1.0 version of the Schema. When running in (Sun) JDK 1.6 the test was successful in that the validator did in fact complain; but on (Sun) JDK 1.5 the validator simply did not complain at all. 1.5 and 1.6 appear to be using different internal SchemaFactory implementations. 1.6 used com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory, while 1.5 used com.sun.org.apache.xerces.internal.jaxp.validation.xs.SchemaFactoryImpl.
Perhaps I am just doing something wrong? The code can be seen at https://fisheye2.atlassian.com/browse/Hibernate/core/trunk/core/src/main/java/org/hibernate/util/xml/MappingReader.java?r=20321#l118 (its the commented out code).
Assuming I did not make a mistake, what is the best way around this?