Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to annotate a list using @XmlElement?

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();            }  } 
like image 564
user3429010 Avatar asked Jun 19 '14 12:06

user3429010


People also ask

What is the use of @XmlElement?

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.

What is XmlTransient annotation?

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.

What is @XmlType annotation in Java?

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.

What is the use of XmlAccessorType?

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.


1 Answers

You need to leverage @XmlElementWrapper and @XmlElement.

Java Model

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 Code

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> 

For More Information

Below are links to a couple articles from my blog that provide additional information:

  • http://blog.bdoughan.com/2010/09/jaxb-collection-properties.html
  • http://blog.bdoughan.com/2012/12/jaxb-representing-null-and-empty.html
like image 185
bdoughan Avatar answered Sep 28 '22 22:09

bdoughan