Will I Am
Will I Am

Reputation: 2672

Jaxb and unmarshalling included XSD

I have two XSDs where one XSD contains an element that can contain elements from the second one. Basically, XSD 1 has an element "etta" which can contain any element from XSD 2.

I used xjc to generate the classes, and when it is deserialized, the Meta element contains the elements from XSD 2 as JAXBElements instead of the actual classes generated from XSD 2. I included both sets of classes into my program, and the package-info is correct.

This is how I defined my XSD. I imagine the problem is my "any" element.

<xs:schema xmlns="NS1" elementFormDefault="qualified"
           xmlns:ns1="NS2"
           targetNamespace="NS1" xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:import  namespace="NS2" schemaLocation="./NS2.xsd" />

    <xs:complexType name="Meta">
        <xs:sequence>
            <xs:any  namespace="NS2" minOccurs="1" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
...
</xs:schema>

So basically what I want is the element to mean "Here goes one or more elements that are defined in XSD2" and would like jaxb to unmarshall it.

How should I change my XSD to help jaxb deserialize contents of Meta using elements from XSD2?

--edit-

This is what xjc generated for the Meta class:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Meta", propOrder = {
    "any"
})
public class Meta
    extends BaseObject
{

    @XmlAnyElement(lax = true)
    protected List<Object> any;

    public List<Object> getAny() {
        if (any == null) {
            any = new ArrayList<Object>();
        }
        return this.any;
    }

}

-- EDIT original XSD2 (changed NS to match the question) --

<xs:schema xmlns="NS2" elementFormDefault="qualified" targetNamespace="syncml:NS2" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="MetInf">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="1" ref="FieldLevel" />
                <xs:element minOccurs="0" maxOccurs="1" ref="Format" />
                <xs:element minOccurs="0" maxOccurs="1" ref="Type" />
                <xs:element minOccurs="0" maxOccurs="1" ref="Mark" />
                <xs:element minOccurs="0" maxOccurs="1" ref="Size" />
                <xs:element minOccurs="0" maxOccurs="1" ref="Anchor" />
                <xs:element minOccurs="0" maxOccurs="1" ref="Version" />
                <xs:element minOccurs="0" maxOccurs="1" ref="NextNonce" />
                <xs:element minOccurs="0" maxOccurs="1" ref="MaxMsgSize" />
                <xs:element minOccurs="0" maxOccurs="1" ref="MaxObjSize" />
                <xs:element minOccurs="0" maxOccurs="unbounded" ref="EMI" />
                <xs:element minOccurs="0" maxOccurs="1" ref="Mem" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="FieldLevel">
        <xs:complexType />
    </xs:element>
    <xs:element name="Format" type="xs:string" />
    <xs:element name="Type" type="xs:string" />
    <xs:element name="Mark" type="xs:string" />
    <xs:element name="Size" type="xs:string" />
    <xs:element name="Anchor">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="1" ref="Last" />
                <xs:element ref="Next" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="Last" type="xs:string" />
    <xs:element name="Next" type="xs:string" />
    <xs:element name="Version" type="xs:string" />
    <xs:element name="NextNonce" type="xs:string" />
    <xs:element name="MaxMsgSize" type="xs:string" />
    <xs:element name="MaxObjSize" type="xs:string" />
    <xs:element name="EMI" type="xs:string" />
    <xs:element name="Mem">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="1" ref="SharedMem" />
                <xs:element ref="FreeMem" />
                <xs:element ref="FreeID" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="FreeID" type="xs:string" />
    <xs:element name="FreeMem" type="xs:string" />
    <xs:element name="SharedMem">
        <xs:complexType />
    </xs:element>
</xs:schema>

-- this is how the Meta is being used in my XSD1:

<xs:element name="TargetRef" type="xs:string" />
  <xs:element name="VerDTD" type="xs:string" />
  <xs:element name="VerProto" type="xs:string" />
  <xs:element name="Item">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="1" ref="Target" />
        <xs:element minOccurs="0" maxOccurs="1" ref="Source" />
        <xs:element minOccurs="0" maxOccurs="1" ref="SourceParent" />
        <xs:element minOccurs="0" maxOccurs="1" ref="TargetParent" />
        <xs:element minOccurs="0" maxOccurs="1" ref="Meta" />
        <xs:element minOccurs="0" maxOccurs="1" ref="Data" />
        <xs:element minOccurs="0" maxOccurs="1" ref="MoreData" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="Meta" type="xs:string" />
  <xs:element name="Correlator" type="xs:string" />
  <xs:element name="Data" type="xs:string" />

Upvotes: 0

Views: 728

Answers (1)

giro
giro

Reputation: 431

How about sth. like this:

Inserting all possible elements from your second xsd into the sequence while defining the minOccurs and maxOccurs in the sequence instead of the elements themselves. (The code is from here - Example 2)

<xs:element name="Meta">
    <xs:complexType>
        <xs:sequence minOccurs="1" maxOccurs="unbounded">
            <xs:element name="elements" type="ns1:typeA"/>
            <xs:element name="from" type="ns1:typeB"/>
            <xs:element name="NS2" type="ns1:typeC"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

Another option would require changing the second xsd a little bit:

instead of line 2-4 looking like this:

<xs:element name="MetInf">
    <xs:complexType>
        <xs:sequence>

they would have to look like this:

        <xs:complexType name="MetInf">
            <xs:sequence>

And the NS1.xsd would look like this:

<xs:schema 
    xmlns="NS1"
    elementFormDefault="qualified"
    targetNamespace="NS1" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ns1="NS2">

<xs:import  namespace="NS2" schemaLocation="NS2.xsd" />

<xs:complexType name="Meta">
    <xs:sequence>
        <xs:element name="metaInf" type="ns1:MetInf" minOccurs="1" maxOccurs="unbounded"/>
    </xs:sequence>
</xs:complexType>

when running xjc with firstSchema.xsd and NS2.xsd in the same directory the following classes are generated:

ns2/Anchor.java
ns2/FieldLevel.java
ns2/Mem.java
ns2/MetInf.java
ns2/ObjectFactory.java
ns2/SharedMem.java
ns2/package-info.java
ns1/Meta.java
ns1/ObjectFactory.java
ns1/package-info.java

The Meta class I get for the firstSchema.xsd looks like this:

public class Meta {

@XmlElement(required = true)
protected List<MetInf> metaInf; 
public List<MetInf> getMetaInf() {
    if (metaInf == null) {
        metaInf = new ArrayList<MetInf>();
    }
    return this.metaInf;
}
}

Is that anywhere near what you need?

Upvotes: 1

Related Questions