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