Nicolas Frankel is an IT consultant with 10 years experience in Java / JEE environments. He likes his job so much he writes technical articles on his blog and reviews technical books in his spare time. He also tries to find other geeks like him in universities, as a part-time lecturer. Nicolas is a DZone MVB and is not an employee of DZone and has posted 229 posts at DZone. You can read more from them at their website. View Full User Profile

XML Validation with Imported/Included Schemas

09.02.2012
| 4479 views |
  • submit to reddit

Recently, I tried to help a teammate design a WSDL file. I gently drove him toward separating the interface itself in the WSDL file and domain objects in a XML Schema file. One thing leading to another, I also made him split this XSD into two separate files, one including another for design purposes. Alas, tests were already present, and they failed miserably after my refactoring, complaining about a type in the included file not being found. The situation was extremely unpleasant, not only because I looked a little foolish in front of one of my co-worker, but also because despite my best efforts, I couldn’t achieve validation.

I finally found the solution, and I hope to spread it as much as I can in order for other developers to stop loosing time regarding this issue. The root of the problem is that the Java XML validation API cannot resolved included XML schemas (and imported ones as well), period. However, it allows for registering a (crude) resolver that can provide the content of the included/imported XSD. So, the solution is to implement your own resolver and your own content holder (there’s none provided in the JDK 6).

  1. Create a “input” implementation. This class is responsible for holding the content of the resolved schema.
    public class LSInputImpl implements LSInput {
     
        private Reader characterStream;
        private InputStream byteStream;
        private String stringData;
        private String systemId;
        private String publicId;
        private String baseURI;
        private String encoding;
        private boolean certifiedText;
     
        // Getters and setters here
    }
  2. Create a resolver implementation. This one is based on the premise that the included/imported schemas lies at the root of the classpath, and is relatively simple. More complex implementations can provide for a variety of locations (filesystem, internet, etc.).
    public class ClasspathResourceResolver implements LSResourceResolver {
     
        @Override
        public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
     
            LSInputImpl input = new LSInputImpl();
     
            InputStream stream = getClass().getClassLoader().getResourceAsStream(systemId);
     
            input.setPublicId(publicId);
            input.setSystemId(systemId);
            input.setBaseURI(baseURI);
            input.setCharacterStream(new InputStreamReader(stream));
     
            return input;
        }
    }
  3. Finally, just set the resolver on the schema factory:
    SchemaFactory schemaFactory = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
     
    schemaFactory.setResourceResolver(new ClasspathResourceResolver());

These 3 steps will go a long way toward cleanly splitting your XML schemas.

From http://blog.frankel.ch/xml-validation-with-importedincluded-schemas

Published at DZone with permission of Nicolas Frankel, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)