prev table of contents next

6.2.7.8 Annotations for Mixed Content: XmlElementRef, XmlMixed

An XML complex type with mixed content, i.e., child elements embedded in the element's own data, cannot be bound to a class in the usual bean style, with one field for each element and attribute, and another one for the content text. Doing so would lose the order of the sub-elements and the chunks of content text wherein they are embedded. JAXB binds such a type to a class containing a single list attribute typed List<JAXBElement>. Here is a schema snippet for a complex type with mixed content:

<xs:complexType name="MessageType" mixed="true">
  <xs:sequence>
    <xs:element name="id"    type="xs:int"/>
    <xs:element name="code"  type="CodeType"/>
  </xs:sequence>
</xs:complexType>
To achieve the same effect with an annotated class, you would write an annotated Java class like this:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MessageType", propOrder = {
    "content"
})
public class MessageType {
    @XmlElementRefs( {
        @XmlElementRef(name = "code", type = JAXBElement.class),
        @XmlElementRef(name = "id",   type = JAXBElement.class) })
    @XmlMixed
    protected List<Serializable> content;
 
    public List<Serializable> getContent() {
        if (content == null) {
            content = new ArrayList<Serializable>();
        }
        return this.content;
    }
}
The generic parameter for the content list is Serializable, slightly more specific than Object. When you process the elements of the content list after unmarshalling, you'll have to distinguish between JAXBElement objects for the sub-elements and String objets for the chunks of the content of the element itself.

A similar but rarely encountered situation is created by duplicating an element in a sequence. Below is a slightly modified version of the schema snippet for the complex type MessageType, which doesn't have mixed content any more, but contains a repetition of element id (ours not to worry why):

<xs:complexType name="MessageType">
  <xs:sequence>
    <xs:element name="id"      type="xs:int"/>
    <xs:element name="code"    type="CodeType"/>
    <xs:element name="id"      type="xs:int"/>
  </xs:sequence>
</xs:complexType>
The annotated Java code would be similar to the one shown previously, except that XmlMixed is omitted and the generic parameter for List should be JAXBElement<?>.
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Message", propOrder = { "content" } )
public class Message { 
    @XmlElementRefs({
        @XmlElementRef(name = "id",   type = JAXBElement.class),
        @XmlElementRef(name = "code", type = JAXBElement.class),
        @XmlElementRef(name = "id",   type = JAXBElement.class)
    })
    protected List<JAXBElement<?>> content;
    public List<JAXBElement<?>> getContent() {
        if (content == null) {
            content = new ArrayList<JAXBElement<?>>();
        }
        return this.content;
    }
}
This does, in fact, marshal or unmarshal many more sub-element sequences than the one shown in the schema snippet, with arbitrary alternations of all three elements.


prev table of contents next