Reputation: 6163
I am working with JAXB to marshal and unmarshal a java class.
This is the xml I'm looking for:
<tag name="example" attribute1="enumValue"/>
if attribute1 is set to the default value, I don't want that attribute to print at all, so it would look like this:
<tag name="example"/>
Is there a way to do this?
Right now I have a getter/setter pair that looks like this:
@XmlAttribute(name="attribute1")
public EnumExample getEnumExample() {
return this.enumExample;
}
public void setEnumExample(final EnumExample enumExample) {
this.enumExample = enumExample;
}
Upvotes: 4
Views: 2510
Reputation: 149047
You could use an XmlAdapter
for this use case:
XmlAdapter (Attribute1Adapter)
You could leverage the fact that JAXB will not marshal null attribute values and use an XmlAdapter
to adjust the value being marshalled to XML.
import javax.xml.bind.annotation.adapters.XmlAdapter;
import forum16972549.Tag.Foo;
public class Attribute1Adapter extends XmlAdapter<Tag.Foo, Tag.Foo>{
@Override
public Foo unmarshal(Foo v) throws Exception {
return v;
}
@Override
public Foo marshal(Foo v) throws Exception {
if(v == Foo.A) {
return null;
}
return v;
}
}
Domain Model (Tag)
The @XmlJavaTypeAdapter
annotation is used to associate the XmlAdapter
.
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Tag {
enum Foo {A, B};
@XmlAttribute
@XmlJavaTypeAdapter(Attribute1Adapter.class)
private Foo attribute1;
public Foo getAttribute1() {
return attribute1;
}
public void setAttribute1(Foo attribute1) {
this.attribute1 = attribute1;
}
}
Demo
Below is some demo code you can use to prove that everything works.
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Tag.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Tag tag = new Tag();
tag.setAttribute1(Tag.Foo.A);
System.out.println(tag.getAttribute1());
marshaller.marshal(tag, System.out);
tag.setAttribute1(Tag.Foo.B);
System.out.println(tag.getAttribute1());
marshaller.marshal(tag, System.out);
}
}
Output
Below is the output from running the demo code.
A
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<tag/>
B
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<tag attribute1="B"/>
Upvotes: 5
Reputation: 149047
Tag
You could leverage the fact that JAXB will not marshal null attribute values and add some logic to your properties and then use JAXB to map to the field.
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Tag {
private static Foo ATTRIBUTE1_DEFAULT = Foo.A;
enum Foo {A, B};
@XmlAttribute
private Foo attribute1;
public Foo getAttribute1() {
if(null == attribute1) {
return ATTRIBUTE1_DEFAULT;
}
return attribute1;
}
public void setAttribute1(Foo attribute1) {
if(ATTRIBUTE1_DEFAULT == attribute1) {
this.attribute1 = null;
} else {
this.attribute1 = attribute1;
}
}
}
Demo
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Tag.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Tag tag = new Tag();
tag.setAttribute1(Tag.Foo.A);
System.out.println(tag.getAttribute1());
marshaller.marshal(tag, System.out);
tag.setAttribute1(Tag.Foo.B);
System.out.println(tag.getAttribute1());
marshaller.marshal(tag, System.out);
}
}
Output
A
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<tag/>
B
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<tag attribute1="B"/>
Upvotes: 2
Reputation: 61
AFAIK, this is not possible directly using JAXB annotations. But using required=true like this,
@XmlAttribute(required=true name="attribute1")
private String enumExample;
we can do a workaround. Before calling the setter on that attribute, we can check if the value that will be set is the default value. If yes, we can pass null to that setter and that attribute will not be visible after marshalling.
Upvotes: 1