JAXB - empty tags without xsi: nil

I have a String property in an object annotated as follows:

@XmlElement(name = "Item", required = true, nillable = true) private String item; 

Result after Marshaling

 <Item xsi:nil="true"/> 

while I would like him to be

 <Item/> 

as the third party service receiving my XML messages wants this to be like the last case. I am using jaxb2. Does anyone know how I could do this?

thanks a lot

+6
source share
2 answers

Note. I am an EclipseLink JAXB (MOXy) and a member of the JAXB Group (JSR-222) .

The following example requires the use of MOXy as a JAXB provider. This is because JAXB RI does not invoke the XmlAdapter when the field / property is null. For information on specifying MOXy as a JAXB provider, see:

StringAdapter

XmlAdapter converts a String value into an object with a property annotated with @XmlValue .

 package forum8986842; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlAdapter; public class StringAdapter extends XmlAdapter<StringAdapter.AdaptedString, String>{ @Override public String unmarshal(AdaptedString adaptedString) throws Exception { if(null == adaptedString) { return null; } String string = adaptedString.value; if("".equals(string)) { return null; } return string; } @Override public AdaptedString marshal(String string) throws Exception { AdaptedString adaptedString = new AdaptedString(); adaptedString.value = string; return adaptedString; } public static class AdaptedString { @XmlValue public String value; } } 

Root

The @XmlJavaTypeAdapter annotation @XmlJavaTypeAdapter used to specify the XmlAdapter :

 package forum8986842; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement(name="Root") public class Root { private String item; @XmlElement(name = "Item", required = true, nillable = true) @XmlJavaTypeAdapter(StringAdapter.class) public String getItem() { return item; } public void setItem(String item) { this.item = item; } } 

Demo

The following code can be used to demonstrate the above mapping. Two documents are used, one with an empty Item , and the other with a filled Item .

 package forum8986842; import java.io.StringReader; import javax.xml.bind.*; public class Demo { private JAXBContext jc; public Demo() throws JAXBException { jc = JAXBContext.newInstance(Root.class); } public static void main(String[] args) throws Exception { Demo demo = new Demo(); demo.demo("<Root><Item/></Root>"); demo.demo("<Root><Item>Hello World</Item></Root>"); } private void demo(String xml) throws JAXBException { System.out.println("\n\nINPUT: " + xml); StringReader stringReader = new StringReader(xml); Unmarshaller unmarshaller = jc.createUnmarshaller(); Root root = (Root) unmarshaller.unmarshal(stringReader); System.out.println("ITEM: " + root.getItem()); System.out.print("OUTPUT: "); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); marshaller.marshal(root, System.out); } } 

Exit

The following is the result of running the demo code:

 INPUT: <Root><Item/></Root> ITEM: null OUTPUT: <Root><Item/></Root> INPUT: <Root><Item>Hello World</Item></Root> ITEM: Hello World OUTPUT: <Root><Item>Hello World</Item></Root> 

Additional Information

+1
source

I found that changing xsd was easier

 <xs:element name="name"> <xs:complexType/> </xs:element> 

and in your code when you automatically create java src / classes

you must specify a new name and set the name depending on which object name belongs

0
source

Source: https://habr.com/ru/post/906757/


All Articles