1
votes

I have a rather complex setup.
I have a super project (all Maven) and two sub projects. The two sub projects are unrelated. I am designing classes in all projects and annotating them with JAXB annotations in order to create XSDs on each sub project level. Each sub project is supposed to incorporate the XML classes from the super project. There is no need for XSDs on the super project level.

In the super project I have several packages that all have a package-info.java file like this:

@javax.xml.bind.annotation.XmlSchema(elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns = {
    @javax.xml.bind.annotation.XmlNs(prefix = "projectA", namespaceURI = "https://some.url.to/projectA"),
    @javax.xml.bind.annotation.XmlNs(prefix = "projectB", namespaceURI = "https://some.url.to/projectB")
})

For simplicity, let's call the sub-projects projectA and projectB.
As mentioned, in the sub-projects I also have several packages with package-info.java files looking like this:

@javax.xml.bind.annotation.XmlSchema(namespace = "https://some.url.to/projectA", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)

In project(A|B) I am generating an XSD schema from this setup. This works fine and all references from the sub projects to the super project are found and resolved.

JAXB generates two XSD files for each sub project. Let's stick to project A in the following examples. Then, schema1.xsd has to following header:

<xs:schema elementFormDefault="qualified" version="1.0" targetNamespace="https://some.url.to/projectA" xmlns:tns="https://some.url.to/projectA" xmlns:xs="http://www.w3.org/2001/XMLSchema">

followed by

<xs:import schemaLocation="schema2.xsd"/>

schema2.xsd has this header:

<xs:schema elementFormDefault="qualified" version="1.0" xmlns:projectB="https://some.url.to/projectB" xmlns:projectA="https://some.url.to/projectA" xmlns:xs="http://www.w3.org/2001/XMLSchema">

Please note that for some reason projectB is included here even though it is not referenced in the XSD. It is the other way around in Project B.

In schema1.xsd I find lines like:

<xs:element name="a_name" type="a_type_in_schema2"/>
<xs:element name="another_name" type="tns:a_type_in_schema1" use="required"/>

While in schema2.xsd I find lines like:

<xs:element name="something" type="another_type_in_schema2" form="unqualified"/>

Note the "unqualified" attribute. It appears at every element that is of a complex type defined in schema2.xsd, too.

This means, all content from the super project is contained in schema2.xsd while all content only defined in project A is in schema1.xsd.

Getting to the point, what I want to do is write XMLs that validate against this setup of XSDs, however I fail to do that.
The header of the XML is:

<rootNode xmlns="https://some.url.to/projectA" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://some.url.to/projectA https://some.url.to/projectA.xsd">

In this XML whenever I try to reference a type that is defined in schema2.xsd (= type from super project) like

<a_type_in_schema1>
    <a_type_in_schema2 .... />
</a_type_in_schema1>

xmllint (and Eclipse, too) will complain:

element a_type_in_schema2: Schemas validity error : Element '{https://some.url.to/projectA}a_type_in_schema2': This element is not expected. Expected is one of ( a, b, c, a_type_in_schema2, d, e).

How can I possibly write it correctly?

Please note that I do not wish to use qualifying tags like <namespace:a_type_in_schema2>. I wish to only use "plain" XML tags because of usability. Can this be done?

1

1 Answers

1
votes

Seems I am a lone fighter with JAXB in 2019. However, after talking to the rubber duck mainly by writing this question, I tried a few more combinations and the solution is this:

Both, the super and the sub projects have to be in the same namespace. I didn't go for this solution at first since I thought I would not be able to validate the sub project XSDs separately. But this is possible.

So, in the super project I only added

@javax.xml.bind.annotation.XmlSchema(namespace = "https://some.url.to/commonNS", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)

The same schema definition was used in both sub projects.

Then, in the XML header I can write

<rootNode xmlns="https://some.url.to/commonNS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://some.url.to/commonNS https://some.url.to/projectA.xsd">

Note the important change in the xsi_schemaLocation. I can here validate the commonNS namespace with a specific XSD. In project B I would use a reference to its XSD instead.

So I have one namespace but different XSD files to validate a given XML which is exactly what I need.