2010-11-16 8 views
2

Je suis mise à niveau d'un objet Java qui a actuellement une représentation XML dans cet esprit:annoter l'ajout d'un attribut à un élément

<myObjects> 
    <myObject uid="42" type="someEnum"> 
     <name>Waldo</name> 
     <description>yada yada</description> 
     <myElement>some_string</myElement> 
     ... 
    </myObject> 
    ... 
</myObjects> 

myElement est en option - il peut être nulle en Java/omis dans XML.
Je suis l'ajout d'un champ qui est seulement pertinent si myElement a une valeur réelle (et pour maintenir la compatibilité avec XML précédent, il est facultatif en lui-même)

J'essaie d'éviter ceci:

<myElement>some_string</myElement> 
    <myAttr>foo</myAttr> 

et préfèrent quelque chose comme ceci:

<myElement myAttr="foo">some_string</myElement> 

mais cognant ma tête pendant 2 jours w sur comment l'annoter.

  • Je pensais que de marquer avec XmlTransient et laissez un XmlAnyElement l'attraper à la place tout en unmarshalling - mais il semble que cela causera un problème lors du débranchement l'objet de retour de Java vers XML.
  • J'ai essayé de créer un XmlAdapter pour l'élément - mais la méthode unmarshal n'obtient que le contenu interne ("some_string"). Est-ce qu'il me manque quelque chose avec cette technique?
  • est-il un moyen de juste obtenir l'élément sous forme de chaîne ("< myElement myAttr = \ "foo \" > some_string </myElement >") et je vais processus moi-même?
  • Recommandez-vous une autre approche?
+0

Nous devons voir votre java – skaffman

+0

Si ce n'était pas clair - je dois seulement garder la compatibilité avec les fichiers XML précédents. Et je peux faire ce que je veux avec le code Java. Donc, intentionnellement, je ne l'ai pas fourni, afin de ne pas vous biaiser (Blaise Doughan l'a interféré assez bien ci-dessous). – targumon

Répondre

3

Vous pouvez utiliser la EclipseLink JAXB (MOXy) extension @XmlPath facilement accomplir ceci:

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlRootElement; 

import org.eclipse.persistence.oxm.annotations.XmlPath; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class MyObject { 

    @XmlAttribute 
    private int uid; 

    @XmlAttribute 
    private String type; 

    private String name; 

    private String description; 

    private String myElement; 

    @XmlPath("myElement/@myAttr") 
    private String myAttr; 

} 

Cette classe va interagir avec le code XML suivant:

<myObject uid="42" type="someEnum"> 
    <name>Waldo</name> 
    <description>yada yada</description> 
    <myElement myAttr="foo">some_string</myElement> 
</myObject> 

En utilisant le code de démonstration ci-dessous:

import java.io.File; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.Unmarshaller; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(MyObject.class); 

     File file = new File("input.xml"); 
     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     MyObject myObject = (MyObject) unmarshaller.unmarshal(file); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(myObject, System.out); 
    } 

} 

Pour spécifier MOXy comme implémentation JAXB, vous devez inclure un fichier appelé jaxb.propriétés dans le même package que vos classes de modèle avec l'entrée suivante:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

Pour plus d'informations sur la cartographie basée XPath de Moxy voir:

+0

Finalement, je n'ai pas utilisé votre solution (voir ci-dessous ma propre réponse). Mais j'ai appris beaucoup de votre explication et de votre blog, donc je l'ai marqué comme "accepté" :-) – targumon

1

La réponse était mort simple: je suis tellement habitué à annoter avec XmlElement et XmlAttribute, que j'ai oublié à propos de XmlValue!

Le code pour MyObject est le même que pour répondre Blaise Doughan, avec un seul changement: myElement est maintenant une classe (ElemWithAttr) au lieu de chaîne:

public class ElemWithAttr { 
    @XmlValue 
    public String content; 

    @XmlAttribute 
    public String myAttr; 
} 
Questions connexes