Verwenden Sie JAXB, um ein Objekt aus einer XML-Zeichenfolge zu erstellen

174

Wie kann ich den folgenden Code verwenden, um eine XML-Zeichenfolge zu entfernen und sie dem unten stehenden JAXB-Objekt zuzuordnen?

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
quelle

Antworten:

282

Um XML-Inhalte zu übergeben, müssen Sie den Inhalt in a Readereinschließen und stattdessen Folgendes entschlüsseln:

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

StringReader reader = new StringReader("xml string here");
Person person = (Person) unmarshaller.unmarshal(reader);
Skaffman
quelle
6
Könnten Sie diese Antwort erweitern, um einzuschließen, ob die "XML-Zeichenfolge hier" einen SOAP-Umschlag enthält?
JWiley
Was wäre, wenn Sie eine Readerin Kombination mit einer bestimmten Bohnenklasse verwenden möchten? Da gibt es keine unmarshall(Reader, Class)Methode. Gibt es zB eine Möglichkeit, das Readerin ein umzuwandeln javax.xml.transform.Source?
Bvdb
2
In meinem Fall arbeiten als:JAXBElement<MyObject> elemento = (JAXBElement<MyObject>)unmarshaller.unmarshal(reader); MyObject object = elemento.getValue();
Cesar Miguel
1
@bvdb Sie können verwenden, javax.xml.transform.stream.StreamSourcewelche Konstruktoren Readerhaben File, oder InputStream.
Muhd
Vielen Dank! In meinem Fall musste ich etwas anderes machen: Person person = (Person) ((JAXBElement) unmarshaller.unmarshal (reader)). GetValue ();
Gustavo Amaro
161

Oder wenn Sie einen einfachen Einzeiler wollen:

Person person = JAXB.unmarshal(new StringReader("<?xml ..."), Person.class);
Andrejs
quelle
1
Dies sollte die akzeptierte Antwort sein. Das ist etwas weniger kompliziert.
Bobbel
Sehr einfach. Ich stimme vollkommen zu, es muss die akzeptierte Antwort sein.
Afaria
5
Ich bin mit den obigen Kommentaren nicht einverstanden. Es ist sicherlich einfacher, aber es erstellt den Kontext im laufenden Betrieb, sodass es Auswirkungen auf die Leistung haben kann, selbst wenn der Kontext zwischengespeichert wird. Mit Vorsicht verwenden.
Crystark
Was ist also die Alternative, wenn wir dem Unmarshaller eine Klasse bieten wollen? Die einzige Methode ist ein (Knoten, Klasse) Parameter und hier haben wir eine Zeichenfolge.
Charles Follet
Mit dieser übersichtlichen Version erhalte ich keine Analysefehler, die zum Debuggen einer Konfiguration nützlich sind. Wahrscheinlich fehlt mir etwas ...
Biber
21

Es gibt keine unmarshal(String)Methode. Sie sollten Folgendes verwenden Reader:

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

Aber normalerweise erhalten Sie diese Zeichenfolge von irgendwoher, zum Beispiel aus einer Datei. Wenn das der Fall ist, geben Sie es besser FileReaderselbst weiter.

Bozho
quelle
3

Wenn Sie bereits über die XML-Datei verfügen und mehr als ein Attribut haben, können Sie damit wie folgt umgehen:

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());
}

Die Methode getCharacterDataFromElement lautet

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

return cd.getData();
}
return "";
}
Miguel Zapata
quelle