Question

I am receiving XML from a server whose schema specifies nearly every element as:

<xs:element name="myStringElementName" type="xs:string" nillable="true" minOccurs="0"/>
<xs:element name="myIntElementName" type="xs:int" nillable="true" minOccurs="0"/>

I'm trying to find a clean way to convert every element that I receive that is marked as xsi:nil="true" to a null when it is unmarshalled into a JAXB object. So something like this:

<myIntElementName xsi:nil="true" />

Should result in my JAXB object having a myIntElementName property with a value of null, rather than a JAXBElement object with a nil property set to true (or anything along those lines). I don't have any control over the system that is sending me the XML that uses the nillable attribute, so I need to convert this on my end when I receive it.

Was it helpful?

Solution

@XmlElement(nillable=true)

You just need to specify @XmlElement(nillable=true) on your field/property to get this behaviour:

@XmlElement(nillable=true)
private String foo;

Generating From an XML Schema

Below I'll demonstrate how to generate this mapping if you are staring from an XML schema.

XML Schema (schema.xsd)

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="foo">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="myStringElementName" type="xs:string"
                    nillable="true" minOccurs="0" />
                <xs:element name="myIntElementName" type="xs:int"
                    nillable="true" minOccurs="0" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Why you get a property of type JAXBElement

A property of type JAXBElement is generated in your model because you have a nillable element this is minOccurs="0". The use of JAXBElement allows the model to differentiate between an missing element (property is null) and the presence of the element with nil="true" (JAXBElement with nil flag set).

<xs:element name="myStringElementName" type="xs:string"
                        nillable="true" minOccurs="0" />

External Binding File (binding.xml)

An external binding file can be specified to tell the JAXB implementation not to generate any properties of type JAXBElement. Note this will make it impossible for JAXB to round trip all XML documents.

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings version="2.0"
               xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
    <jaxb:bindings>
        <jaxb:globalBindings generateElementProperty="false"/>
    </jaxb:bindings>
</jaxb:bindings>

XJC Call

Below is an example of how to leverage an external binding file from the XJC Call

xjc -b binding.xml schema.xsd

Generated Model (Foo)

The generated model will look something like the following:

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "myStringElementName",
    "myIntElementName"
})
@XmlRootElement(name = "foo")
public class Foo {

    @XmlElement(nillable = true)
    protected String myStringElementName;
    @XmlElement(nillable = true)
    protected Integer myIntElementName;

    public String getMyStringElementName() {
        return myStringElementName;
    }

    public void setMyStringElementName(String value) {
        this.myStringElementName = value;
    }

    public Integer getMyIntElementName() {
        return myIntElementName;
    }

    public void setMyIntElementName(Integer value) {
        this.myIntElementName = value;
    }

}

For More Information

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top