Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB List of Choice

Tags:

jaxb

xsd

xjc

I have following schema

<complexType name="BookShelf">
   <sequence>
      <element name="newBook" type="string" minOccurs="0" maxOccurs="unbounded"/>
      <element name="oldBook" type="string" minOccurs="0" maxOccurs="unbounded"/>
   </sequence>
</complexType>

XJC generates BookShelf class with two lists, one for newBook and one for oldBook. Excellent!

Now I want books to appear in any order. So I rewrite my schema to:

<complexType name="BookShelf">
   <sequence>
      <choice minOccurs="0" maxOccurs="unbounded">
         <element name="newBook" type="string"/>
         <element name="oldBook" type="string"/>
      </choice>
   </sequence>
</complexType>

But now XJC generates BookShelf with only one list newBookOrOldBook of type List<JAXBElement<String>>.

I don't care about the order in which books appear and I want to allow XML writer to specify books in any order he\she wishes, but I still want books of each type as List in generated BookShelf class. Is there any way I can achieve this?

like image 365
olek Avatar asked Nov 14 '22 15:11

olek


1 Answers

You can use the Simplify plugin from JAXB2 Basics. It can simplify @XmlElements and @XmlElementRefs properties, which makes things a lot easier, if you don't really care about the order. Here's an example (excerpt from the documentation):

Consider the following choice:

<xs:complexType name="typeWithReferencesProperty">
    <xs:choice maxOccurs="unbounded">
        <xs:element name="a" type="someType"/>
        <xs:element name="b" type="someType"/>
    </xs:choice> 
</xs:complexType>

This will normally generate a property like:

@XmlElementRefs({
    @XmlElementRef(name = "a", type = JAXBElement.class),
    @XmlElementRef(name = "b", type = JAXBElement.class)
})
protected List<JAXBElement<SomeType>> aOrB;

You can use the simplify:as-element-property element to remodel this complex property as two element properties or simplify:as-reference-property as two reference properties.

Not that in the case of a reference property, you have to customize one of the xs:element and not the xs:choice.

<xs:complexType name="typeWithReferencesProperty">
    <xs:choice maxOccurs="unbounded">
        <xs:element name="a" type="someType">
            <xs:annotation>
                <xs:appinfo>
                    <simplify:as-element-property/>
                </xs:appinfo>
            </xs:annotation>
        </xs:element>
        <xs:element name="b" type="someType"/>
    </xs:choice> 
</xs:complexType>

Results in:

@XmlElement(name = "a")
protected List<SomeType> a;
@XmlElement(name = "b")
protected List<SomeType> b;
like image 82
lexicore Avatar answered Jan 13 '23 02:01

lexicore