I have the following annotation using javax.xml.bind.annotation.XmlElement
:
@XmlElement public List<String> getKeywords() { return keywords; }
Which produces the following XML when I marshall some example content:
<keywords>keyword1</keywords> <keywords>keyword2</keywords>
I would like to get the following XML:
<keywords> <keyword>keyword1</keyword> <keyword>keyword2</keyword> </keywords>
What kind of an annotation should I use?
I've tried
@XmlElementWrapper @XmlElement(name="keyword")
But then the whole content disappears and the result is:
<keywords/>
The same happens also if I only try to rename the element:
@XmlElement(name="keyword")
What am I doing wrong?
UPDATE:
Here is the updated full code for the class according to the first answers, but it is still not working (the result is an empty list <keywords/>
when marshalled to XML):
import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Content { private List<String> keywords; public Content() {} @XmlElementWrapper(name="keywords") @XmlElement(name="keyword") public List<String> getKeywords() { return keywords; } public void setKeywords(List<String> keywords) { this.keywords = keywords; } }
I also tried the following with the same result:
import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Content { @XmlElementWrapper(name="keywords") @XmlElement(name="keyword") private List<String> keywords; public Content() {} public List<String> getKeywords() { return keywords; } public void setKeywords(List<String> keywords) { this.keywords = keywords; } }
However, the keywords are not empty as the following produces <keywords>keyword1</keywords><keywords>keyword2</keywords>
instead of an empty list:
import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Content { private List<String> keywords; public Content() {} @XmlElement public List<String> getKeywords() { return keywords; } public void setKeywords(List<String> keywords) { this.keywords = keywords; } }
The code for marshalling is (JAX-RS):
import java.io.StringWriter; import javax.ws.rs.Consumes; import javax.ws.rs.Path; import javax.ws.rs.POST; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; @Path("process") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_XML) public class ContentHandler { @POST public Response process(Content content) { StringWriter stringWriter = new StringWriter(); try { JAXBContext jaxbContext = JAXBContext.newInstance(Content.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.marshal(content, stringWriter); } catch (JAXBException e) { return Response.serverError().entity(e.getMessage()).build(); } return Response.ok(stringWriter.toString(), MediaType.APPLICATION_XML).build(); } }
A JavaBean property, when annotated with @XmlElement annotation is mapped to a local element in the XML Schema complex type to which the containing class is mapped.
Annotation Type XmlTransientPrevents the mapping of a JavaBean property/type to XML representation. The @XmlTransient annotation is useful for resolving name collisions between a JavaBean property name and a field name or preventing the mapping of a field/property.
The annotation element propOrder() in the @XmlType annotation allows you to specify the content order in the generated schema type. When you use the @XmlType. propOrder annotation on a class to specify content order, all public properties and public fields in the class must be specified in the parameter list.
Annotation Type XmlAccessorTypeControls whether fields or Javabean properties are serialized by default. @XmlAccessorType annotation can be used with the following program elements: package. a top level class.
You need to leverage @XmlElementWrapper
and @XmlElement
.
Content
import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement public class Content { private List<String> keywords; public Content() {} @XmlElementWrapper @XmlElement(name="keyword") public List<String> getKeywords() { return keywords; } public void setKeywords(List<String> keywords) { this.keywords = keywords; } }
Demo
import java.util.*; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Content.class); List<String> strings = new ArrayList<String>(2); strings.add("foo"); strings.add("bar"); Content content = new Content(); content.setKeywords(strings); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(content, System.out); } }
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <content> <keywords> <keyword>foo</keyword> <keyword>bar</keyword> </keywords> </content>
Below are links to a couple articles from my blog that provide additional information:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With