Utilisez JAXB pour créer un objet à partir d'une chaîne XML

174

Comment puis-je utiliser le code ci-dessous pour démarseler une chaîne XML et la mapper à l'objet JAXB ci-dessous?

JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Person person = (Person) unmarshaller.unmarshal("xml string here");

@XmlRootElement(name = "Person")
public class Person {
    @XmlElement(name = "First-Name")
    String firstName;
    @XmlElement(name = "Last-Name")
    String lastName;
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}
c12
la source

Réponses:

282

Pour transmettre du contenu XML, vous devez envelopper le contenu dans un Reader, et démarshal cela à la place:

JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

StringReader reader = new StringReader("xml string here");
Person person = (Person) unmarshaller.unmarshal(reader);
skaffman
la source
6
Pourriez-vous développer cette réponse pour inclure si la "chaîne xml ici" inclut une enveloppe SOAP?
JWiley
Et si vous vouliez utiliser un Readeren combinaison avec une classe de haricots spécifique? Puisqu'il n'y a pas de unmarshall(Reader, Class)méthode. Existe-t-il par exemple un moyen de convertir le Readeren un javax.xml.transform.Source?
bvdb
2
Dans mon cas, travaillez comme:JAXBElement<MyObject> elemento = (JAXBElement<MyObject>)unmarshaller.unmarshal(reader); MyObject object = elemento.getValue();
Cesar Miguel
1
@bvdb Vous pouvez utiliser javax.xml.transform.stream.StreamSourcequi a des constructeurs qui prennent Reader, Fileou InputStream.
Muhd
Merci! Dans mon cas, j'avais besoin de faire un peu différent: Person person = (Person) ((JAXBElement) unmarshaller.unmarshal (reader)). GetValue ();
Gustavo Amaro
162

Ou si vous voulez un simple one-liner:

Person person = JAXB.unmarshal(new StringReader("<?xml ..."), Person.class);
Andrejs
la source
1
Cela devrait être la réponse acceptée. C'est un peu moins compliqué.
bobbel
Très simple. Je suis tout à fait d'accord, ce doit être la réponse acceptée.
Afaria
5
Je ne suis pas d'accord avec les commentaires ci-dessus. C'est certes plus simple, mais cela crée le contexte à la volée, ce qui peut avoir des impacts sur les performances même si le contexte finit par être mis en cache. Utiliser avec précaution.
Crystark
Alors, quelle est l'alternative si nous voulons fournir une classe au démarshaller? La seule méthode prend un (nœud, classe) en paramètre et nous avons ici une chaîne.
Charles Follet
Avec cette version concise, je ne reçois pas d'erreurs d'analyse, utiles pour déboguer une configuration. Il me manque probablement quelque chose ...
castor
21

Il n'y a pas de unmarshal(String)méthode. Vous devez utiliser un Reader:

Person person = (Person) unmarshaller.unmarshal(new StringReader("xml string"));

Mais généralement, vous obtenez cette chaîne de quelque part, par exemple un fichier. Si tel est le cas, mieux vaut passer le FileReaderlui - même.

Bozho
la source
4

Si vous avez déjà le xml et que plusieurs attributs sont fournis, vous pouvez le gérer comme suit:

String output = "<ciudads><ciudad><idCiudad>1</idCiudad>
<nomCiudad>BOGOTA</nomCiudad></ciudad><ciudad><idCiudad>6</idCiudad>
<nomCiudad>Pereira</nomCiudad></ciudads>";
DocumentBuilder db = DocumentBuilderFactory.newInstance()
    .newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(output));

Document doc = db.parse(is);
NodeList nodes = ((org.w3c.dom.Document) doc)
    .getElementsByTagName("ciudad");

for (int i = 0; i < nodes.getLength(); i++) {           
    Ciudad ciudad = new Ciudad();
    Element element = (Element) nodes.item(i);

    NodeList name = element.getElementsByTagName("idCiudad");
    Element element2 = (Element) name.item(0);
    ciudad.setIdCiudad(Integer
        .valueOf(getCharacterDataFromElement(element2)));

    NodeList title = element.getElementsByTagName("nomCiudad");
    element2 = (Element) title.item(0);
    ciudad.setNombre(getCharacterDataFromElement(element2));

    ciudades.getPartnerAccount().add(ciudad);
}
}

for (Ciudad ciudad1 : ciudades.getPartnerAccount()) {
System.out.println(ciudad1.getIdCiudad());
System.out.println(ciudad1.getNombre());
}

la méthode getCharacterDataFromElement est

public static String getCharacterDataFromElement(Element e) {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;

return cd.getData();
}
return "";
}
Miguel Zapata
la source