javaxmlxsdsaxparserxml-validation

XML validation against XSD with javax.xml.validation.Validator: cannot resolve types come from 2nd XSD


I am trying to write a method that validates XML against XSD. In my case, I have multiple XSD files.

When I use tools like IntelliJ IDEA to generate a sample XML from my main XSD everything looks fine: the sample XML is generated and looks as I expect. So I think that my XSD files are okay.

This is my simplified main XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:ds="http://www.w3.org/2000/09/xmldsig#">

    <xsd:import schemaLocation="xmldsig-core-schema.xsd" namespace="http://www.w3.org/2000/09/xmldsig#" />

    <xsd:element name="Message">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="messageId" type="xsd:string" />
                <xsd:element ref="ds:Signature" minOccurs="0" />
            </xsd:sequence>
            <xsd:attribute name="Id" type="xsd:string" use="optional"/>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

I downloaded and put the xmldsig-core-schema.xsd in the same directory with my XSD files.

The error I get:

org.xml.sax.SAXParseException: src-resolve: Cannot resolve the name 'ds:Signature' to a(n) 'element declaration' component.

Java code:

InputStream xsdStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("schema/my.xsd");
// 1. InputStream xsdSignatureStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("schema/xmldsig-core-schema.xsd");

Source[] sources = new StreamSource[1];
sources[0] = new StreamSource(xsdStream);
// 2. sources[1] = new StreamSource(xsdSignatureStream);

SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
// 3. schemaFactory.setResourceResolver(new ClasspathResourceResolver());
Schema schema = schemaFactory.newSchema(sources);

Validator validator = schema.newValidator();

String xmlString = "...";
StringReader xmlStringReader = new StringReader(xmlString)
Source source = new StreamSource(xmlStringReader);
validator.validate(source);

So it seems that the javax.xml.validation.Validator does not see my 2nd XSD file. So I tried to add it when I initialize the javax.xml.validation.Schema but it does not help (see commented lines 1. and 2.).

I also tried to create and add an external ResourceResolver (see commented line 3.), but it does not help.

Comment: The streams I use are initialized properly, the file paths are good, I can read the content from streams and log it as strings.

What I miss here?


Solution

  • I suspect that when the schema document is loaded using getResourceAsStream("schema/my.xsd"); it doesn't have a known base URI and therefore the relative URI xmldsig-core-schema.xsd doesn't resolve properly. Try setting a base URI (systemId property) on your StreamSource object.