Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example using multiple sources for validation #18

Open
moaxcp opened this issue Apr 14, 2023 · 2 comments
Open

Example using multiple sources for validation #18

moaxcp opened this issue Apr 14, 2023 · 2 comments

Comments

@moaxcp
Copy link

moaxcp commented Apr 14, 2023

Hello. Thanks for this awesome library. It has helped me catch many issues in our xml rendering.

I am running into an issue with validation using two xsds with namespaces.

I have setup the assertion like this.

assertThat(result)
                            .isValidAgainst(vmapXsdSource(), vast3XsdSource())
                            .and("""
                                    <vmap:VMAP xmlns:vmap="http://www.iab.net/videosuite/vmap" version="1.0"/>
                                    """)
                            .ignoreWhitespace()
                            .areIdentical();

The sources are on github.

https://github.com/InteractiveAdvertisingBureau/vmap/blob/5412bbe033ba9573b517619b1b4fa2027987a0d3/xsd/vmap.xsd
https://github.com/InteractiveAdvertisingBureau/vast/blob/f28dbb4768744062fcb638a1859364cdafb3a449/vast3_draft.xsd

vmap.xsd references vast in one location and it is causing me issues.

    <xs:complexType name="VASTAdData_type">
        <xs:sequence>
            <xs:element ref="vast:VAST" minOccurs="1" maxOccurs="1"/>
        </xs:sequence>
    </xs:complexType>

This is where the sources are created.

    private Source vmapXsdSource() {
        var source = Input.fromStream(getClass().getResourceAsStream("response_templates/xsd/vmap.xsd")).build();
        source.setSystemId("http://www.iab.net/videosuite/vmap");
        return source;
    }

    private Source vast3XsdSource() {
        var source = Input.fromStream(getClass().getResourceAsStream("response_templates/xsd/vast3_draft.xsd")).build();
        source.setSystemId("http://www.iab.net/videosuite/vast");
        return source;
    }

I tried setting the system id but it doesn't seem to help. This is the error I now get.

Caused by: org.xml.sax.SAXParseException; systemId: http://www.iab.net/videosuite/vmap; lineNumber: 1; columnNumber: 1; Premature end of file.

The wiki says

when validating a DTD with XMLUnit for Java you may need to set schemaURI to the Public ID of the schema so that XMLUnit's EntityResolver can provide the schema to the parser.

But I'm not sure where schema comes into play when using .isValidAgainst. Is that a different type of Source?

I couldn't find an example of using multiple xsd files to validate xml output.

I can live without validation but it would be nice to have an example of this working somewhere in the documentation.

@bodewig
Copy link
Member

bodewig commented Apr 16, 2023

I must admit I have never tried to do that.

Note the comment about systemId is about DTDs while you are using XML Schema validation.

Under the covers what XMLUnit does is to combine the sources given via https://docs.oracle.com/javase/7/docs/api/javax/xml/validation/SchemaFactory.html#newSchema(javax.xml.transform.Source[]) - and reading the javadoc it may not be doing what you expect. To me this seems to parse the sources into a single schema with no target namespace.

I'm not even sure what it would mean that a document was valid against multiple schemas. Most likely you'd only be validating against "vmap" and want to help the validator to find the "vast" schema that is referenced by vmap.

In addition it's been ages since I last touched any code in this area so read what I write with big grains of salt.

Ignoring XMLUnit's API for now and looking at SchemaFactory I believe you only want to specify the vmap schema as Source and use setResourceResolver on the factory to help it resolving the vast schema. Unfortunately this is not currently possible using XMLUnit's API. It shouldn't be too difficult to extends JAXPValidator to accept and pass on an LSResourceResolver. Please don't ask why they introduced LSInput rather than rely on Source.

Also I'm not quite sure whether resource resolution happens during the newSchema call or after the validator starts validating - it might be safest to add the LSResourceResolver to the SchemaFactory as well as the Validator.

This is starting to become an implementation rather than a documentation issue :-)

If you wanted to take a stab at playing with this, this would be great. You know the context you want to use it in - and to be honest it might take me some time to find a slice of undisturbed time to set up a test case and play with the API myself. If you don't want to try yourself, I'll do my best to to figure this out but can't make any promises.

@moaxcp
Copy link
Author

moaxcp commented May 8, 2023

What I got to in the code is here.

image

ValidationAssert is created with schemaSources but schema is null. Then when validate is called the sources should be populated in the validator.

image

When generating the schema it is called with multiple sources.

image

newSchema should combine the two sources into one schema.

This is just what I have so far. I'm going to try creating a validator outside of xmlunit to see what happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants