Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with JAXB Collections

Tags:

java

jaxb

I am trying to unmarshall the following XML using JAXB:

<Works>
    <Work>
        <Composers>
            <Composer>
                <Name>A name</Name>
            </Composer>
            <Composer>
                <Name>A name 2</Name>
            </Composer>
        </Composers>
    </Work>
</Works>

I have generated all of the classes using XJC. If I want to access the Composers collection, I have to do this:

 List<Composer> composers = work.getComposers().getComposer();

Is there any way I can do the following instead?

 List<Composer> composers = work.getComposers();

I appreciate the need for a Composers object as it derived from the XML, but when dealing in Java, having an intermediate POJO that stores the collections seems a bit redundant.

My XSD is:

<xsd:complexType name="Works">
    <xsd:sequence>
        <xsd:element name="Work" type="Work" maxOccurs="unbounded" minOccurs="0"></xsd:element>
    </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="Work">
    <xsd:sequence>
        <xsd:element name="Composers" type="Composers"></xsd:element>
    </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="Composers">
    <xsd:sequence>
        <xsd:element name="Composer" type="Composer" maxOccurs="unbounded" minOccurs="0"></xsd:element>
    </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="Composer">
    <xsd:sequence>
        <xsd:element name="Name" type="xsd:string"></xsd:element>
    </xsd:sequence>
</xsd:complexType>

like image 268
seedhead Avatar asked Sep 07 '11 17:09

seedhead


2 Answers

The @XmlElementWrapper plugin does exactly what you want.

like image 92
William Brendel Avatar answered Oct 16 '22 20:10

William Brendel


For anybody who can not or does not want to use the plugin: If you can live with a different XML structure, it's possible to avoid generating the extra wrapper classes by simply using maxoccurs="unbounded" and leaving out the containing element. Using the original example:

<xsd:element name="Work" type="Work" maxOccurs="unbounded" minOccurs="0"/>

<xsd:complexType name="Work">
    <xsd:sequence>
        <xsd:element name="Composer" type="Composer" maxOccurs="unbounded" minOccurs="0"/>
    </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="Composer">
    <xsd:sequence>
        <xsd:element name="Name" type="xsd:string"></xsd:element>
    </xsd:sequence>
</xsd:complexType>

will produce a structure like this:

<Work>
    <Composer>
        <Name>A name</Name>
    </Composer>
    <Composer>
        <Name>A name 2</Name>
    </Composer>
</Work>

This will put a method on the Work type that returns a List<Composer> object. Unfortunately the method is called getComposer instead of getComposers, but you can use annotations or custom bindings to fix that problem.

like image 25
undefined Avatar answered Oct 16 '22 19:10

undefined