How to represent null value as empty element with JAXB?

Viewed 55896

My XSD structure is like the below:-

<element name="XYZDate" maxOccurs="1" minOccurs="1" nillable="true" type="date"/>

When I set the null value in this field it allow me but at he time of XML Generation from JAXB marshaling it produce the output with

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

Whereas in the result I want the out put as <XYZDate/> i.e. do not want the schema and other attribute.
I get rid of this with the help of using XMLStreamWriter but it produce the complete XML in Single line. I need formatted well formed XML. If I need to use IndentingXMLStreamWriter my Java version do not support it and I do not have control over Java Container to change or modify.

Please suggest any solution to form XML Well Formatted.

4 Answers

Blaise's answer is good but it is outdated. There is a much better and simpler method to achieve the same. I have searched many forums and combined different solutions to get to this. I am sharing here so that it will be helpful for others.


Note: The below solution is more general case than just for date.


Method - 1 : If you want to replace all null values with empty string in xml

Session Event Adapter Class

Add the below class to a convenient package in your code.

package com.dev

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;
import org.eclipse.persistence.oxm.mappings.nullpolicy.XMLNullRepresentationType;
import org.eclipse.persistence.sessions.*;

public class NullPolicySessionEventListener extends SessionEventAdapter {

@Override
public void preLogin(SessionEvent event) {
    Project project = event.getSession().getProject();
    for(ClassDescriptor descriptor : project.getOrderedDescriptors()) {
        for(DatabaseMapping mapping : descriptor.getMappings()) {
            if(mapping.isAbstractDirectMapping()) {
                XMLDirectMapping xmlDirectMapping = (XMLDirectMapping) mapping;
                xmlDirectMapping.getNullPolicy().setMarshalNullRepresentation(XMLNullRepresentationType.EMPTY_NODE);
                xmlDirectMapping.getNullPolicy().setNullRepresentedByEmptyNode(true);
            }
        }
    }
 }

}

Entity Class

package com.dev;

import javax.xml.bind.annotation.*;

import org.eclipse.persistence.oxm.annotations.*;

@XmlRootElement(name = "Entity")
public class Entity {

    @XmlElement(name = "First_Name", required=true, nillable = true)
    private String firstName;

    @XmlElement(name = "Last_Name" , required=true, nillable = true)
    private String lastName;

    public Entity(){}

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

}

DemoApp Class

package com.dev;

import javax.xml.bind.*;
import org.eclipse.persistence.*;
import java.util.Map;
import java.util.HashMap;

public class DemoApp {

public static void main(String[] args) throws Exception {
    Map<String, Object> properties = new HashMap<String,Object>(1);
    SessionEventListener sessionEventListener = new NullSessionEventListener();
    properties.put(JAXBContextProperties.SESSION_EVENT_LISTENER, sessionEventListener);
    JAXBContext context = JAXBContextFactory.createContext(new Class[] {ListofEntities.class, list.get(0).getClass()},properties);
    Marshaller marshaller = jc.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

    Entity entity = new Entity();
    entity.setfirstName(null);
    entity.setLastName(null);
    marshaller.marshal(entity, System.out);

    entity.setfirstName("Ramu");
    entity.setLastName("K");
    marshaller.marshal(entity, System.out);
}

}

Output:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <First_Name/>
   <Last_Name/>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root>
   <First_Name>Ramu</First_Name>    
   <Last_Name>Ramu</Last_Name>   
</root>

Method - 2 : If you want to replace only selected null values with empty string in xml

Entity Class

package com.dev;

import javax.xml.bind.annotation.*;

import org.eclipse.persistence.oxm.annotations.*;

@XmlRootElement(name = "Entity")
public class Entity {

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

    @XmlElement(name = "Last_Name" , required=true, nillable = true)
    private String lastName;

    public Entity(){}

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

}

DemoApp Class

package com.dev;

import javax.xml.bind.*;
import org.eclipse.persistence.*;

public class DemoApp {

public static void main(String[] args) throws Exception {
    JAXBContext context = JAXBContextFactory.createContext(new Class[] {ListofEntities.class, list.get(0).getClass()},null);
    Marshaller marshaller = jc.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

    Entity entity = new Entity();
    entity.setfirstName(null);
    entity.setLastName(null);
    marshaller.marshal(entity, System.out);

    entity.setfirstName("Ramu");
    entity.setLastName("K");
    marshaller.marshal(entity, System.out);
}

}

Output:

In this output, we see only the element with XmlNullPolicy annotation is shown when value is null. The other element is omitted because of default behavior of jaxb.

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <First_Name/>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root>
   <First_Name>Ramu</First_Name>    
   <Last_Name>Ramu</Last_Name>   
</root>

References:

  1. Where to include jaxb.properties file?

  2. Represent null value as empty element in xml jaxb

Related