Ritesh
Ritesh

Reputation: 1143

Output empty elements

I have a Object with two fields "name" and "address". JAXB ignores the empty elements while transforming the object into XMl.

For ex: if I have name="xyz" and address=null then out will be

<name>xyz</name>

but what I want as an output as

<name>xyz</name>
<address></address>

I have seen the option @XmlElement(nillable="true") but this gives the output as

<name>xyz</name>
<address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>

Please help me getting the desired output.

Thanks in advance.

Upvotes: 8

Views: 25884

Answers (3)

ndr_brt
ndr_brt

Reputation: 121

Simply set an empty string default value on the field.

@XmlElement(required="true")
private String address = "";

and you will get

<address></address>

Upvotes: 0

L&#234; văn Huy
L&#234; văn Huy

Reputation: 371

If you use EclipseLink MOXy as your JAXB provider then you could use

@XmlNullPolicy(emptyNodeRepresentsNull = true, nullRepresentationForXml = XmlMarshalNullRepresentation.EMPTY_NODE)
@XmlElement(name = "address", nillable = true)
private String address;

By using this way, you don't have to write adapter for all the fields

Upvotes: 1

bdoughan
bdoughan

Reputation: 149007

A JAXB (JSR-222) implementation will output an empty String "" value as an empty element. You can set the address property to this to get the desired effect.


UPDATE #1

I have updated my question. Basically the address element is NULL. Is this solution applicable to that as well?

You could leverage Marshal Event Callbacks to adjust the value of address.

import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

    private String name;
    private String address;

    private void beforeMarshal(Marshaller marshaller) {
        if(null == address) {
            address = "";
        }
    }

    private void afterMarshal(Marshaller marshaller) {
        if("".equals(address)) {
            address = null;
        }
    }

}

UPDATE #2

The only concern is that if I have 10 fields in the class I will have to write if for all the fields. Is there any other solution?

If you use EclipseLink MOXy as your JAXB provider (I'm the MOXy lead), then you could use an XmlAdapter for this use case.

XmlAdapter (StringAdapter)

package forum14691333;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class StringAdapter extends XmlAdapter<String, String> {

    @Override
    public String marshal(String string) throws Exception {
        if(null == string) {
            return "";
        }
        return string;
    }

    @Override
    public String unmarshal(String string) throws Exception {
        if("".equals(string)) {
            return null;
        }
        return string;
    }

}

package-info

Then if you specify it at the package level it will apply to all mapped fields/properties of type String within that package.

@XmlJavaTypeAdapter(value=StringAdapter.class, type=String.class)
package forum14691333;

import javax.xml.bind.annotation.adapters.*;

For More Information

Upvotes: 9

Related Questions