0
votes

In my program, I am generating a XML file, and need to validate that XML file against multiple schemas which are located on different URLs. Its required to validate that XML file against all schema in onetime only.

Source fragment:

// here source array contain the locations of schemas, located at diff servers.
Source[] source = {
        new StreamSource(
                new URL("http://localhost:8081/test1/testSchema1.xsd")
                        .openStream()),
        new StreamSource(
                new URL(
                        "http://ccr.internal.ericsson.com/test2/testSchema2.xsd")
                        .openStream()) };

try {
    // Compile the schema, which loaded from schemaFileLocation.
    Schema schemaGrammar = schemaFactory.newSchema(source);

    // Create a validator for schema.
    Validator configValidator = schemaGrammar.newValidator();

    // set error handler with validator.
    SchemaValidator schemaValidator = new SchemaValidator();
    configValidator
            .setErrorHandler(schemaValidator.new MessageHandler());

    // validate xml instance against the grammar.
    configValidator.validate(new StreamSource(new File("xmlFile.xml")));
    System.out.println("\n");
} catch (SAXException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

When I run the above code fragment, I am get this error:

org.xml.sax.SAXParseException: src-resolve: Cannot resolve the name 'xn:SubNetwork' to a(n) 'element declaration' component. at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source) at org.apache.xerces.util.ErrorHandlerWrapper.error(Unknown Source) at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDHandler.reportSchemaError(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDHandler.getGlobalDecl(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDElementTraverser.traverseLocal(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDElementTraverser.traverseLocal(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDAbstractParticleTraverser.traverseSeqChoice(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDAbstractParticleTraverser.traverseChoice(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDComplexTypeTraverser.processComplexContent(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDComplexTypeTraverser.traverseComplexTypeDecl(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDComplexTypeTraverser.traverseLocal(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDElementTraverser.traverseNamedElement(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDElementTraverser.traverseLocal(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDHandler.traverseLocalElements(Unknown Source) at org.apache.xerces.impl.xs.traversers.XSDHandler.parseSchema(Unknown Source) at org.apache.xerces.impl.xs.XMLSchemaLoader.loadSchema(Unknown Source) at org.apache.xerces.impl.xs.XMLSchemaLoader.loadGrammar(Unknown Source) at org.apache.xerces.impl.xs.XMLSchemaLoader.loadGrammar(Unknown Source) at org.apache.xerces.jaxp.validation.XMLSchemaFactory.newSchema(Unknown Source) at com.work.test.generateErrorLog(SchemaValidator.java:197)

What is the problem in code? Is their is any other way to validate against multiple schema?

2

2 Answers

1
votes

There are quite a few posts regarding this topic and I could not find a satisfying solution either. Here is how it worked for me. Give the SchemaFactory a custom resource resolver


    Source source = new StreamSource(this.getClass().getResourceAsStream("ebics.xsd"));
    LSResourceResolver resolver = new ResourceResolver(schemaFactory.getResourceResolver());
    schemaFactory.setResourceResolver(resolver);
    

and parse only the top level schema. The resolver can then (hopefully) resolve the embedded references


public class ResourceResolver implements LSResourceResolver {
    private LSResourceResolver parent = null;
    private Set returnedResources = new HashSet();


    public ResourceResolver(LSResourceResolver r){
    parent = r;
    }

    private ResourceResolver() {
    }

    public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
    LSInput input = new LSInputImpl();

    if (returnedResources.contains(systemId)) {
        return null;
    } else if (systemId.equals("ebics_hev.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_hev.xsd"));
    } else if (systemId.equals("ebics_keymgmt_request.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_keymgmt_request.xsd"));
    } else if (systemId.equals("ebics_keymgmt_response.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_keymgmt_response.xsd"));
    } else if (systemId.equals("ebics_orders.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_orders.xsd"));
    } else if (systemId.equals("ebics_request.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_request.xsd"));
    } else if (systemId.equals("ebics_response.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_response.xsd"));
    } else if (systemId.equals("ebics_signature.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_signature.xsd"));
    } else if (systemId.equals("ebics_types.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_types.xsd"));
    } else if (systemId.equals("ebics.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics.xsd"));
    } else if (systemId.equals("xmldsig-core-schema.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("xmldsig-core-schema.xsd"));
    } else {
        return parent.resolveResource(type, namespaceURI, publicId, systemId, baseURI);
    }
    returnedResources.add(systemId);
    return input;
    }

}

Here is the LSInputImpl


public class LSInputImpl implements LSInput
{

    public Reader getCharacterStream () {
        return null;
    }

    public void setCharacterStream ( Reader characterStream ) {}

    public InputStream getByteStream () {
        InputStream retval = null;
        if ( byteStream != null ) {
            retval = byteStream;
        }
        return retval;
    }

    public void setByteStream ( InputStream byteStream ) {
        this.byteStream = byteStream;
    }

    public String getStringData () {
        return null;
    }

    public void setStringData ( String stringData ) {}

    public String getSystemId () {
        return systemId;
    }

    public void setSystemId ( String systemId ) {
        this.systemId = systemId;
    }

    public String getPublicId () {
        return null;
    }

    public void setPublicId ( String publicId ) {}

    public String getBaseURI () {
        return null;
    }

    public void setBaseURI ( String baseURI ) {}

    public String getEncoding () {
        return null;
    }

    public void setEncoding ( String encoding ) {}

    public boolean getCertifiedText () {
        return false;
    }

    public void setCertifiedText ( boolean certifiedText ) {}


    private String systemId = null;
    private InputStream byteStream = null;
}

1
votes

I had the same problem.

I switched the order of the schemas.

First i imported all child schemas and at the end i set the main schema.

Source[] sources = new Source[] { new StreamSource(new InputStreamReader(SomeClass.class.getResourceAsStream("/com/foo/subschema1.xsd"), "UTF-8")), 
                              new StreamSource(new InputStreamReader(SomeClass.class.getResourceAsStream("/com/foo/subschema2.xsd"), "UTF-8")),
                              new StreamSource(new InputStreamReader(SomeClass.class.getResourceAsStream("/com/foo/subschema3.xsd"), "UTF-8")),
                              ...
                              new StreamSource(new InputStreamReader(SomeClass.class.getResourceAsStream("/com/foo/mainschema.xsd"), "UTF-8"))};