Dealing with JAXB Collections

2019-02-09 04:34发布

问题:

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>

回答1:

The @XmlElementWrapper plugin does exactly what you want.



回答2:

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.



标签: java jaxb