How can I add xml attributes to jaxb annotated class XmlElementWrapper?
I got a better solution for your question.
For making Xml Java object, use the following code:
import java.util.*;import javax.xml.bind.annotation.*;@XmlRootElement(name="myList")public class Root { private String number; private List<String> someList; @XmlAttribute(name="number") public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } @XmlElement(name="myElement") public List<String> getSomeList() { return someList; } public void setSomeList(List<String> someList) { this.someList = someList; } public Root(String numValue,List<String> someListValue) { this(); this.number = numValue; this.someList = someListValue; } /** * */ public Root() { // TODO Auto-generated constructor stub }
}
To run the above code using JAXB, use the following:
import java.util.ArrayList;import java.util.List;import javax.xml.bind.*;public class Demo { public static void main(String[] args) throws Exception { List<String> arg = new ArrayList<String>(); arg.add("FOO"); arg.add("BAR"); Root root = new Root("123", arg); JAXBContext jc = JAXBContext.newInstance(Root.class); Marshaller marshaller = jc.createMarshaller(); marshaller.marshal(root, System.out); }}
This will produce the following XML as the output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <myList number="123"> <myElement>FOO</myElement> <myElement>BAR</myElement> </myList>
I think this is more helpful you.
Thanks..
The MOXy JAXB implementation (I'm the tech lead) has an extension (@XmlPath) to handle this case:
import java.util.*;import javax.xml.bind.annotation.*;import org.eclipse.persistence.oxm.annotations.XmlPath;@XmlRootElement@XmlAccessorType(XmlAccessType.FIELD)public class Root { @XmlPath("myList/@number") private int number; @XmlElementWrapper(name="myList") @XmlElement(name="myElement") private List<String> someList = new LinkedList<String>(); public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public List<String> getSomeList() { return someList; } public void setSomeList(List<String> someList) { this.someList = someList; } }
Will produce the following XML:
<?xml version="1.0" encoding="UTF-8"?><root> <myList number="123"> <myElement>FOO</myElement> <myElement>BAR</myElement> </myList></root>
When this code is run:
import javax.xml.bind.*;public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); Root root = new Root(); root.setNumber(123); root.getSomeList().add("FOO"); root.getSomeList().add("BAR"); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); }}
To get this to work using strictly standard JAXB code you will need to use an XML Adapter:
Note:
To use MOXy JAXB you need to add a file called jaxb.properties in with your model classes with the following entry:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
If you are not using MOXy or just want to stick to standard JAXB annotations, you can extend upon Noby's answer to add support for a generic wrapper class. Noby's answer only currently supports a list of strings, but say for example you're going to be using the same generic wrapper class for several different classes. In my example, I want to create a generic "PagedList" class that will marshall to something that looks like a list, but also contains information about the page offset and the total number of elements in unpaged list.
The one downside of this solution is that you have to add additional @XmlElement mappings for each type of class that will be wrapped. Overall though, probably a better solution than creating a new class for each pagable elements.
@XmlTypepublic class PagedList<T> { @XmlAttribute public int offset; @XmlAttribute public long total; @XmlElements({ @XmlElement(name="order", type=Order.class), @XmlElement(name="address", type=Address.class) // additional as needed }) public List<T> items;}@XmlRootElement(name="customer-profile")public class CustomerProfile { @XmlElement public PagedList<Order> orders; @XmlElement public PagedList<Address> addresses;}
Marshalling this example would get you:
<customer-profile> <order offset="1" total="100"> <order> ... </order> <order> ... </order> <order> ... </order> ... </orders> <addresses offset="1" total="5"> <address> ... </address> <address> ... </address> <address> ... </address> <address> ... </address> <address> ... </address> <addresses></customer-profile>
Hope that helps. This is the solution that I settled upon at least.