I want to add some attributes to Xml Elements using JAXB when marshalling from JavaBeans. The Xml Elements are simple data types like String. So I do not want to create new Classes. For exa开发者_如何学运维mple, a desired output would be:
<notifications>
<date>04/20/2011</date>
<subject creditcard_num="22678" checknum="8904">Credit Card Charge Back</subject>
<body payment_amount="34.00" return_status="charged back">some text</body>
</notifications
I do not want to define subject and body as separate classes.
-Anand
My solution require defining a class for subject and body, but the desired output will be as requested I use @XmlValue for the message and @XmlAttribute for the attributes
@Test
public void testAll() throws JAXBException
{
String msg = "<notifications><date>04/20/2011</date><subject creditcard_num='22678' checknum='8904'>Credit Card Charge Back</subject><body payment_amount='34.00' return_status='charged back'>some text</body></notifications>";
Notifications tested = (Notifications) JAXBContext.newInstance(Notifications.class).createUnmarshaller().unmarshal(new StringReader(msg));
assertEquals("Credit Card Charge Back",tested.subject.value);
assertEquals("8904",tested.subject.checknum);
assertEquals("22678",tested.subject.creditcard_num);
}
@XmlRootElement
public static class Notifications{
public String date;
public Subject subject;
}
public static class Subject
{
@XmlValue
public String value;
@XmlAttribute(name="creditcard_num")
public String creditcard_num;
@XmlAttribute(name="checknum")
public String checknum;
}
NOTE:I only wrote the subject part, I wonder if using @XmlPath can be used to remove the need for different classes
You could use EclipseLink JAXB (MOXy)'s @XmlPath annotation to solve this problem (I'm the MOXy tech lead):
Notifications
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Notifications {
private String date;
@XmlPath("subject/@creditcard_num")
private String creditcardNum;
@XmlPath("subject/@checknum")
private String checknum;
private String subject;
@XmlPath("body/@payment_amount")
private String paymentAmount;
@XmlPath("body/@return_status")
private String returnStatus;
private String body;
}
jaxb.properties
To use MOXy as your JAXB implementation you need to put a file named jaxb.properties in the same package as your model classes with the following entry:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
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(Notifications.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Notifications notifications = (Notifications) unmarshaller.unmarshal(new File("input.xml"));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(notifications, System.out);
}
}
For More Information:
- http://bdoughan.blogspot.com/2010/07/xpath-based-mapping.html
- http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html
- http://bdoughan.blogspot.com/2011/03/map-to-element-based-on-attribute-value.html
精彩评论