Java Model
The following Java model will be used for this example:
The following Java model will be used for this example:
package blog.string2element;
public class Customer {
private String name;
private String status;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
XML (input.xml)
<customer>
<name>Jane Doe</name>
<GOLD/>
</customer>
XML Adapter
In order to have the value represented as an empty element we will need to have a Class corresponding to each possible String value. Then the XmlAdapter will convert between the String and Object values. We will make use of @XmlElementRef on the Customer's status property so each Status class will need an @XmlRootElement annotation.
package blog.string2element;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class StatusAdapter extends XmlAdapter<StatusAdapter.Status, String> {
private static final String GOLD = "GOLD";
private static final String SILVER = "SILVER";
private static final String BRONZE = "BRONZE";
@Override
public String unmarshal(Status v) throws Exception {
if(Gold.class == v.getClass()) {
return GOLD;
} else if(Silver.class == v.getClass()) {
return SILVER;
} else if(Bronze.class == v.getClass()) {
return BRONZE;
}
return null;
}
@Override
public Status marshal(String v) throws Exception {
if(GOLD.equals(v)) {
return new Gold();
} else if(SILVER.equals(v)) {
return new Silver();
} else if(BRONZE.equals(v)) {
return new Bronze();
}
return null;
}
@XmlSeeAlso({Gold.class, Silver.class, Bronze.class})
public static abstract class Status {
}
@XmlRootElement(name=GOLD)
public static class Gold extends Status {
}
@XmlRootElement(name=SILVER)
public static class Silver extends Status {
}
@XmlRootElement(name=BRONZE)
public static class Bronze extends Status {
}
}
Annotated Java Model
In our Java model we will annotate the status property with both @XmlElementRef and @XmlAdapter. This will cause the property value to be derived from the @XmlRootElement values of the adapted classes.
package blog.string2element;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
public class Customer {
private String name;
private String status;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElementRef
@XmlJavaTypeAdapter(StatusAdapter.class)
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
} Demo Code
The following code can be used to demonstrate the solution.
package blog.string2element;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("input.xml");
Customer customer = (Customer) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(customer, System.out);
}
} Further Reading
If you enjoyed this post, then you may also like:
- The following posts are about @XmlAdapter:
- The following post is about @XmlElementRef:
Thanks for the information
ReplyDeletehttp://owntechnology.blogspot.com
how to add annotation to the status property in auto generated classes. We are generating the classes using xjc command.
ReplyDelete