Reputation: 933
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
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
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
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