curious
curious

Reputation: 933

Do XSD imports load automatically on resource loading?

I am using below snippets to make a Schema object inside static block:

URL url = getClass().getClassLoader().getResource("test.xsd");

and test.xsd is importing three other XSD file,

My question is will the imports be available when reference to them will be made (like when validating) , or do I have to load the imports specifically by making URL object.

Upvotes: 0

Views: 567

Answers (3)

Adán Escobar
Adán Escobar

Reputation: 4623

in case that you want to implement an xml validator with xsd resources, you need create a custom LSResourceResolver

for the example: considering that I'm loading a base.xsd that imports "my_complex.xsd","my_types.xsd"

class LSInputImpl implements LSInput {
        private byte[] bytes;
        private String publicId; 
        private String systemId;
        private String baseURI;
...
}
class SchemaResourceResolver implements LSResourceResolver{
    public static List<String> schemas = Arrays.asList("my_complex.xsd","my_types.xsd");

    @Override
    public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId,String baseURI) {
        if(schemas.contains(systemId)){
                LSInputImpl input = new LSInputImpl();
            InputStream in = UtilFile.resourceInputStream("relative/resource/path/"+systemId);
            input.setByteStream(in);
            input.setSystemId(systemId);
            input.setPublicId(publicId);
            input.setBaseURI(baseURI);

            return input;
        }
        return null;
    }
}

public class XmlValidator {


    public static boolean validateSchema(InputStream xsd,InputStream xml ){
        try {
            // Create a SchemaFactory and specify XML schema language
            SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

            // Set the custom resource resolver
            factory.setResourceResolver(new SchemaResourceResolver());
            
            // Load the schema from file
            Schema schema = factory.newSchema(new StreamSource(xsd));

            // Create a Validator instance from the schema
            Validator validator = schema.newValidator();

            // Create a Source from the XML string
            Source source = new StreamSource(xml);

            // Perform the validation
            validator.validate(source);

            // If no exception is thrown, the XML is valid
            System.out.println("XML is valid.");
            return true;
        } catch (SAXException e) {
            System.out.println("XML is not valid: " + e.getMessage());
        } catch (Exception e) {
            System.out.println("Error during XML validation: " + e.getMessage());
        }
        return false;
    }
    public static void main(String[] args) {

        try {
            InputStream xsd = UtilFile.resourceInputStream("relative/resource/path/base.xsd");
            InputStream xml = UtilFile.loadFile("/samples/test.xml");
            validateSchema(xsd, xml);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

for LSInputImpl it is important to transform byteStream to bytes[] for his multiples reads, if not you get the error: unexpected end of file, because input stream is already read

Upvotes: 0

Vadim
Vadim

Reputation: 4120

Because when you use getClass().getClassLoader().getResource("test.xsd"); you do not actually load test.xsd, but only get URL to it you do not need to do anything else.

XSD import has a meaning only to appropriate tools. As example validator.

So, when you pass schema location to validator it can be absolute path, relative path to current working directory or URL.

Then when validator processes XSD it tries to get imports same way - absolute path, relative to the test.xsd schema location or URL as it defined in test.xsd.

Upvotes: 0

kjhughes
kjhughes

Reputation: 111561

No, you'll have to load the imported XSDs explicitly because getResource() has no knowledge of XSD semantics -- it's operating at the resource/file level, not the XSD level.

Upvotes: 0

Related Questions