Repository navigation
Example using multiple sources for validation #18
Description
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.
Activity
bodewig commentedon 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
SchemaFactoryI believe you only want to specify the vmap schema asSourceand usesetResourceResolveron 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 extendsJAXPValidatorto accept and pass on anLSResourceResolver. Please don't ask why they introducedLSInputrather than rely onSource.Also I'm not quite sure whether resource resolution happens during the
newSchemacall or after the validator starts validating - it might be safest to add theLSResourceResolverto theSchemaFactoryas well as theValidator.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 commentedon May 8, 2023
What I got to in the code is here.
ValidationAssert is created with schemaSources but schema is null. Then when validate is called the sources should be populated in the validator.
When generating the schema it is called with multiple sources.
newSchemashould 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.