prev table of contents next

2.2.12.7 Mixed Content

Mixed content lets you embed child elements into the value of an element. One example for the natural application of mixed content would be the representation of text, where parts of a paragraph's text value might have some specific property such as boldface or italic. These stretches are best represented as children of the paragraph element. Here is an example written in some simple markup similar to HTML:

<P>
<B>Mixed content</B> lets you embed <I>child elements</I> 
into the value of an element.
</P>
To see how JAXB handles mixed content, we define a schema for our very simple text markup language. We'll have chunks of text that may be used as an entire paragraph as well as part of a paragraph, to be rendered in boldface, in italics or underlined. The complex type ChunkType has its attribute mixed set to true since we'll want to have plain text as well, and an unbounded repetition of choices as child elements.
<xsd:complexType name="ChunkType" mixed="true">
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="B" type="ChunkType"/>  
      <xsd:element name="I" type="ChunkType"/>  
      <xsd:element name="U" type="ChunkType"/>  
    </xsd:choice>
</xsd:complexType>

<xsd:complexType name="TextType">
  <xsd:sequence>
    <xsd:element name="P" type="ChunkType" maxOccurs="unbounded"/>
  </xsd:sequence>
</xsd:complexType>
The generated Java code is somewhat opaque, as ChunkType features just one method getContent, apparently the Swiss army knife for slicing a chunk of text. The generic list type now happens to be java.lang.Serializable, which is just another way of saying "(almost) anything goes".
public class TextType {
    protected List<ChunkType> p;

    public List<ChunkType> getP() {
        if (p == null) {
            p = new ArrayList<ChunkType>();
        }
        return this.p;
    }
}

public class ChunkType {
    protected List<Serializable> content;

    public List<Serializable> getContent() {
        if (content == null) {
            content = new ArrayList<Serializable>();
        }
        return this.content;
    }
}
The documentation JAXB generates is kind enough to inform us that the elements in the list returned by getContent are either of type String or of type JAXBElement<ChunkType>. As we already know, this is the wrapper class JAXB uses whenever elements have to be distinguished by their tags, and, indeed, we did use ChunkType with B, I and U. Having penetrated this slight obfuscation, we can now write code to process a text as a list of paragraphs. The content list of a text chunk yields plain and decorated chunks in any order.
private static void dumpChunk( ChunkType c ){
    for( Serializable s: c.getContent() ){
        if( s instanceof String ){
            System.out.print( (String)s );
        } else {
            String tag = ((JAXBElement)s).getName().getLocalPart();
            ChunkType chunk = (ChunkType)((JAXBElement)s).getValue();
            System.out.print( "(" + tag + ":" );
	    dumpChunk( chunk );
            System.out.print( ":" + tag + ")" );
	}
    }
}

    //...(process a text)
    TextType text = ...;
    for( ChunkType c: text.getP() ){
        dumpChunk( c );
    }


prev table of contents next