Jax-WS - To Remove Empty Tags from Request XML

ⅰ亾dé卋堺 提交于 2019-11-30 22:16:29

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

By default MOXy like other JAXB implementations will not marshal an element for null values:

POSSIBLE PROBLEM

I believe the strIpAddress property is not null, but contains a value of empty String (""). This would cause the empty element to be written out.

Root

package forum11215485;

import javax.xml.bind.annotation.*;

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

    String nullValue;
    String emptyStringValue;
    String stringValue;

}

Demo

package forum11215485;

import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Root root = new Root();
        root.nullValue = null;
        root.emptyStringValue = "";
        root.stringValue = "Hello World";

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

Output

Note how there is no element marshalled out for the nullValue field, and the emptyStringValue field is marshalled as an empty element.

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <emptyStringValue></emptyStringValue>
   <stringValue>Hello World</stringValue>
</root>

SOLUTION #1 - Ensure the property is set to null and not ""

SOLUTION #2 - Write an XmlAdapter that converts "" to null

An XmlAdapter is a JAXB mechanism that allows an object to be marshalled as another object.

StringAdapter

The following XmlAdapter will marshal empty strings as null. This will cause them not to appear in the XML representation.

package forum11215485;

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

public class StringAdapter extends XmlAdapter<String, String> {

    @Override
    public String unmarshal(String v) throws Exception {
        return v;
    }

    @Override
    public String marshal(String v) throws Exception {
        if(null == v || v.length() == 0) {
            return null;
        }
        return v;
    }

}

package-info

The XmlAdapter is hooked in using the @XmlJavaTypeAdapter annotation. Below is an example of hooking it in at the package level so that it applies to a fields/properties of type String within the package. For more information see: http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html

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

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

Output

Now the output from running the demo code is the following:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <stringValue>Hello World</stringValue>
</root>
ggarciao

This is a problem of the XML Serializer that you are using (If you did not do something special it should be JAXB).

The "null policy" of the serializer should be configurable, but I think is not possible with JAXB. If you use MOXy you can use XmlMarshalNullRepresentation.ABSENT_NODE to do not write the node if it is null. The implementation should be something like this:

class MyClass {

    // ... here are your other attributes

    @XmlElement (name = "strIpAddress")
    @XmlNullPolicy(nullRepresentationForXml = XmlMarshalNullRepresentation.ABSENT_NODE)
    String strIpAddress = null;

}

PS: Maybe you need to define also the emptyNodeRepresentsNull param of the @XmlNullPolicy.

For more information about this subject, please check this question

This worked for me, when serializing a class where I couldn't use annotations (LogRecord):

            JAXBContext jc = JAXBContext.newInstance(LogRecord.class);
            JAXBElement<LogRecord> je = new JAXBElement<>(new QName("log"), LogRecord.class, record);
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setAdapter(new XmlAdapter<String,String>() {
                @Override
                public String marshal(String v) throws Exception {
                    if(null == v || v.length() == 0) {
                        return null;
                    }
                    return v;
                }
                @Override
                public String unmarshal(String v) throws Exception {
                    return v;
                }
            });
            ByteArrayOutputStream xml = new ByteArrayOutputStream();
            marshaller.marshal(je, xml);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!