Search code examples
javaxmljaxbmoxyxjc

How to generate a class using JAXB whose element can contain a string or XML?


I am using JAXB to generate classes from an XML schema. I have an element status in my XML which may contain plain text or XML (or both). For example, the following are all valid content:

<message>
  <status>OK</status>
</message>

<message>
  <status>
    <error>FAIL</error>
  </status>
</message>

<message>
  <status>
    There was an error<error>FAIL</error>
  </status>
</message>

Following this previous question - How to marshall a string using JAXB that sometimes contains XML content and sometimes does not? - I was able to manually adjust the class to marshal and unmarshal successfully, by using a DomHandler.

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
  "status"
})
@XmlRootElement(name = "message")
public class Message
{
  @XmlAnyElement(StatusDomHandler.class)    
  protected String status;

  public String getStatus() { return status; }
  public void setStatus(String value) { this.status = value; }
}

The problem is, I cannot find a way to get JAXB to generate this class. If I write my schema with

<xsd:element name='status' type='xsd:string'/>

then the generated class contains

@XmlElement(required = true)
protected String status;

and I can't add the annotation StatusDomHandler.class as it is not supported by @XmlElement.

But if I write my schema using <xs:any> then the generated class contains an Element which can only represent a single XML element.

Is there any way I can force JAXB to create a string element as @XmlAnyElement? Or is there some other way I can define my schema to allow the generated element to contain either text or XML element(s)?


Solution

  • You could specify that your type has mixed content to get the behaviour you are looking for:

    <xs:element name="message">
        <xs:complexType mixed="true">
            <xs:any/>
        </xs:complexType>
    </xs:element>