À l'aide de @XmlPath avec jaxb/MOXy à la carte de type complexe
J'ai un profond structure XML avec beaucoup d'inutile wrappers je suis cartographie à une seule classe Java. La cartographie de la simple types de données avec @XmlPath est une promenade dans le parc, mais quand il s'agit de types qui ont réellement besoin de leur propre classe, je ne suis pas tout à fait sûr de savoir comment faire, en particulier lorsque ces types de doit être mis dans une liste.
Je vais avoir des problèmes à la carte toutes les element
types dans l'exemple ci-dessous de mon Element
classe. Depuis le elements
wrapper réside dans les ressources qui sont cartographiés à l'aide @XmlPath
je ne peux pas utiliser le @XmlElementWrapper
, qui seraient autrement la façon dont j'ai l'habitude de le faire.
Exemple de la structure XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<s:root xsi:schemaLocation="http://www.example.eu/test ResourceSchema.xsd" xmlns:s="http://www.example.eu/test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<s:resource>
<s:information>
<s:date>2013-07-04</s:date>
<s:name>This example does not work</s:name>
</s:information>
<s:elements>
<s:refobj>
<s:id>1</s:id>
<s:source>First Source</s:source>
</s:refobj>
<s:refobj>
<s:id>2</s:id>
<s:source>Second Source</s:source>
</s:refobj>
<s:refobj>
<s:id>5</s:id>
<s:source>Fifth Source</s:source>
</s:refobj>
</s:elements>
</s:resource>
</s:root>
Root.java
@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlPath("resource/information/date/text()")
private String date;
@XmlPath("s:resource/s:information/s:name/text()")
private String name;
@XmlPath("resource/elements/refobj")
private List<RefObj> refObjs;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
RefObj.java
@XmlRootElement(name = "refobj")
@XmlAccessorType(XmlAccessType.FIELD)
public class RefObj {
@XmlElement(name = "id")
private int id;
@XmlElement(name = "source")
private String source;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
}
Marshaller/Unmarshaller
public static void main(String[] args) {
String xml = getXML();
Root root = null;
try {
JAXBContext context = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
StringReader stringReader = new StringReader(xml);
root = (Root) unmarshaller.unmarshal(stringReader);
} catch (Exception ex) {
System.err.println("Failed to unmarshal XML!");
}
try {
JAXBContext context = JAXBContext.newInstance(Root.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.eu/test ResourceSchema.xsd");
StringWriter stringWriter = new StringWriter();
marshaller.marshal(root, stringWriter);
System.out.println(new String(stringWriter.toString().getBytes(Charset.forName("UTF-8"))));
} catch (Exception ex) {
System.err.println("Failed to marshal object!");
}
}
package-info.java
@XmlSchema(
namespace = "http://www.example.eu/test",
attributeFormDefault = XmlNsForm.QUALIFIED,
elementFormDefault = XmlNsForm.QUALIFIED,
xmlns = {
@XmlNs(
prefix = "s",
namespaceURI = "http://www.example.eu/test")
},
location = "http://www.example.eu/test ResourceSchema.xsd")
package se.example.mavenproject1;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Je peut exécuter l'application, mais aucun élément n'est mappé quand je unmarshal/maréchal du contenu XML, au lieu-je obtenir une représentation XML contenant les informations.
Mise à jour
Après l'affichage de l'exemple précédent, j'ai réalisé qu'en fait, il a fonctionné comme prévu, ce qui m'a fait encore plus confus. Bien que j'ai essayé de reproduire le (déjà) qui travaillent par exemple dans mon code de production, sans succès, bien que j'ai réussi à en fait introduire les problèmes que je vais avoir dans l'exemple de code. Depuis que j'ai besoin d'ajouter un espace de noms pour les problèmes apparaissent, je suis en supposant qu'il a quelque chose à voir avec les conventions de nommage et X(ml)Chemin d'accès.
J'ai aussi ajouté package-info.java
et le marshaller/unmarshaller j'utilise lorsque l'on travaille avec ces objets. Depuis le jaxb.les propriétés ne contient pas de chose d'excitant, je l'ai laissée.
Vous devez vous connecter pour publier un commentaire.
Quand j'ai couru votre exemple tout a bien fonctionné. Depuis votre vrai modèle a probablement des méthodes get/set, vous devez vous assurer que vous ajoutez
@XmlAccessorType(XmlAccessType.FIELD)
à votre classe sinon MOXy (ou tout autre JAXB impl) traiterons également des propriétés correspondantes comme étant mappé (voir: http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html).Vous devez également vous assurer que vous avez un
jaxb.properties
fichier dans le même package que votre modèle de domaine avec l'entrée suivante pour spécifier MOXy que votre JAXB fournisseur (voir: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).Pour Plus D'Informations
Mise à JOUR #1
Lorsque votre document est l'espace de noms qualifiés de la
@XmlPath
annotation doit en tenir compte dans. Les nœuds dans le chemin d'accès peut être qualifié selon la@XmlSchema
annotation.paquet-info
Dans votre
package-info
classe le préfixes
est affecté à l'URI d'espace de nomshttp://www.example.eu/test
.Racine
Cela signifie que les nœuds sont qualifiés avec
http://www.example.eu/test
espace de noms doit avoir le préfixes
dans le@XmlPath
annotation.Mise à JOUR #2
C'est un bug. Vous devriez espace de noms qualifier le
@XmlPath
pour de simples objets de la même façon que pour les objets complexes (voir mise à JOUR #1). La configuration correcte des œuvres d'aujourd'hui, nous allons corriger le bug suivant, de sorte que le mappage incorrect se comporte correctement. Vous pouvez utiliser le lien ci-dessous pour suivre nos progrès sur cette question:Il semble donc que si l'espace de noms doit être spécifié dans le
@XmlPath
lors de la cartographie du chemin d'accès à un objet complexe, mais peut être ignorée lors de la cartographie du chemin d'accès à un objet simple comme unString
ou uninteger
.D'origine, incorrect, code
Mis à jour, code de travail
Lors de l'ajout du préfixe d'espace de noms pour le
@XmlPath
tous les objets sont mappés comme prévu. Si quelqu'un pouvait confirmer cela, et peut-être expliquer pourquoi, je vous en serais très heureux de connaître la raison de ce comportement.@XmlPath
pour à la fois simple et complexe des mappages. Il y a actuellement un bug qui est à l'origine de votre cas simple de travailler. J'ai mis à jour ma réponse avec plus de détails: stackoverflow.com/a/17466836/383861