I have an XML file and two XSD files for it: xsd_1.xsd and xsd_2.xsd. xsd_1.xsd refers to the xsd_2.xsd but it seems that does not load when validation is performed.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="..." targetNamespace="..."
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:include schemaLocation = "http://.../xmlschema/xsd_2.xsd"/>
...
</xsd:schema>
XML file has some simple structure. I use the following code to validate this xml:
Source[] schemes = new StreamSource[] {
new StreamSource("C:/java-projects/xsl/src/test/resources/ex/xsd_1.xsd"),
new StreamSource("C:/java-projects/xsl/src/test/resources/ex/xsd_2.xsd")
};
Source xml = new StreamSource(new File(XML_PATH));
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(schemes);
Validator validator = schema.newValidator();
validator.validate(xml);
I can't validate xml using this code, the following exception is thrown:
org.xml.sax.SAXParseException; systemId: file:///C:/java-projects/xsl/src/test/resources/ex/xsd_1.xsd; lineNumber: 16; columnNumber: 49; src-resolve: Cannot resolve the name 'Elem' to a(n) 'type definition' component.
The Elem
tag is defined in the xsd_2 file.xsd and it looks like this file is not loading.
But the following trick works. If I create a wrapper with these two xsd files, the validation will be successful:
URL firstXsd = XMLValidator.class.getResource(FIRST_XSD_PATH);
URL secondXsd = XMLValidator.class.getResource(SECOND_XSD_PATH);
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
val wrapper =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n "
+ "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" "
+ "targetNamespace=\"...\">\n "
+ "<xs:include schemaLocation=\"" + firstXsd.getPath() + "\"/>\n "
+ "<xs:include schemaLocation=\"" + secondXsd.getPath() + "\"/>\n "
+"</xs:schema>";
Schema schema = schemaFactory.newSchema(new StreamSource(new StringReader(wrapper)));
Validator validator = schema.newValidator();
validator.validate(new StreamSource(new File(XML_PATH)));
This solution is not suitable for a number of reasons. Why I can't validate xml using the first approach?
Perhaps something wrong with this instruction?
<xsd:include schemaLocation = "http://.../xmlschema/xsd_2.xsd"/>
This resource does not exist on the network, all xsd files are stored locally. But I can't make changes to them.
The issue you're facing is related to the way you are specifying the schema locations in the xsd_1.xsd file:
<xsd:include schemaLocation="http://.../xmlschema/xsd_2.xsd"/>
The schemaLocation attribute is expecting a relative or absolute path, but you've provided an HTTP URL. This is likely the reason why xsd_2.xsd is not loading properly during validation.
To fix this issue, you should use a relative or absolute path instead of an HTTP URL. If both XSD files are in the same directory, you can use a relative path like this:
<xsd:include schemaLocation="xsd_2.xsd"/>
Make sure that the paths are correct and that the XSD files are accessible from the location where you are running the validation.
Here's how your corrected xsd_1.xsd might look:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="..." targetNamespace="..."
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:include schemaLocation="xsd_2.xsd"/>
...
</xsd:schema>