Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Output empty elements

Tags:

jaxb

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.

like image 992
Ritesh Avatar asked Feb 04 '13 16:02

Ritesh


People also ask

What are empty elements in XML?

Empty XML ElementsAn element with no content is said to be empty. The two forms produce identical results in XML software (Readers, Parsers, Browsers). Empty elements can have attributes.

What is the use of empty elements?

The empty elements are used to embed images, lists, breaks, horizontal lines, hyperlinks, for input, meta-data, area, etc. For instance, <p> tag had a closing tag hence it was not an empty element.

What is null in XML?

Null fields are saved into XML streams as empty elements. This means that a null field is indistinguishable from an empty string.


1 Answers

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

  • http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html
  • http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
like image 147
bdoughan Avatar answered Oct 11 '22 23:10

bdoughan