J'ai l'annotation suivante en utilisant javax.xml.bind.annotation.XmlElement
:
@XmlElement
public List<String> getKeywords() {
return keywords;
}
Ce qui produit le code XML suivant lorsque je rassemble un exemple de contenu:
<keywords>keyword1</keywords>
<keywords>keyword2</keywords>
Je voudrais obtenir le XML suivant:
<keywords>
<keyword>keyword1</keyword>
<keyword>keyword2</keyword>
</keywords>
Quel type d'annotation dois-je utiliser?
J'ai essayé
@XmlElementWrapper
@XmlElement(name="keyword")
Mais alors tout le contenu disparaît et le résultat est:
<keywords/>
La même chose arrive aussi si j'essaye seulement de renommer l'élément:
@XmlElement(name="keyword")
Qu'est-ce que je fais mal?
METTRE À JOUR:
Voici le code complet mis à jour pour la classe en fonction des premières réponses, mais il ne fonctionne toujours pas (le résultat est une liste vide <keywords/>
lorsque transformé en 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;
}
}
J'ai aussi essayé le suivant avec le même résultat:
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;
}
}
Cependant, les mots-clés ne sont pas vides, car ce qui suit produit <keywords>keyword1</keywords><keywords>keyword2</keywords>
au lieu d'une liste vide:
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;
}
}
Le code pour le marshalling est (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();
}
}
Vous devez utiliser @XmlElementWrapper
et @XmlElement
.
Contenu
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;
}
}
Démo
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);
}
}
Sortie
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<content>
<keywords>
<keyword>foo</keyword>
<keyword>bar</keyword>
</keywords>
</content>
Vous trouverez ci-dessous des liens vers quelques articles de mon blog qui fournissent des informations supplémentaires:
Utilisez ce formulaire:
@XmlElementWrapper(name="keywords")
@XmlElement(name="keyword")
Veuillez noter que si keywords
est vide alors vous obtiendrez <keywords />
.
Parfois, vous devrez ajouter @XmlRootElement
à votre classe (selon le contexte) et l'annotation @XmlAccessorType(XmlAccessType.?)
. J'utilise habituellement @XmlAccessorType(XmlAccessType.FIELD)
et annote mes champs avec @XmlElement
.
Ci-dessus réponse de - Blaise Doughan est complètement correct
Un autre moyen simple est, même si vous n’écrivez pas - @XmlElementWrapper
private List<String> keywords;
@XmlElementWrapper
@XmlElement(name="keyword")
public List<String> getKeywords() {
return keywords;
}
Vous pouvez l'utiliser de cette façon - écrivez XmlAccessorType au niveau de la classe, le nom de l'élément XML sera alors identique au nom du membre de la classe - mots-clés
import Java.util.List;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Content {
private List<String> keywords;
public Content() {}
public List<String> getKeywords() {
return keywords;
}
public void setKeywords(List<String> keywords) {
this.keywords = keywords;
}
}