Gunakan JAXB untuk membuat Objek dari XML String

174

Bagaimana saya bisa menggunakan kode di bawah ini untuk menghapus string XML dan memetakannya ke objek JAXB di bawah ini?

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
sumber

Jawaban:

282

Untuk meneruskan konten XML, Anda harus membungkus konten dalam Reader, dan menghapusnya:

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

StringReader reader = new StringReader("xml string here");
Person person = (Person) unmarshaller.unmarshal(reader);
skaffman
sumber
6
Bisakah Anda memperluas jawaban ini untuk menyertakan jika "string xml di sini" termasuk amplop SOAP?
JWiley
bagaimana jika Anda ingin menggunakan Readerkombinasi dengan kelas kacang tertentu? Karena tidak ada unmarshall(Reader, Class)metode. Misalnya apakah ada cara untuk mengonversi Readerke javax.xml.transform.Source?
bvdb
2
Dalam kasus saya bekerja sebagai:JAXBElement<MyObject> elemento = (JAXBElement<MyObject>)unmarshaller.unmarshal(reader); MyObject object = elemento.getValue();
Cesar Miguel
1
@bvdb Anda dapat menggunakan javax.xml.transform.stream.StreamSourceyang memiliki konstruktor yang mengambil Reader, Fileatau InputStream.
Muhd
Terima kasih! Dalam kasus saya, saya perlu melakukan sedikit berbeda: Person person = (Person) ((JAXBElement) unmarshaller.unmarshal (reader)). GetValue ();
Gustavo Amaro
161

Atau jika Anda menginginkan one-liner sederhana:

Person person = JAXB.unmarshal(new StringReader("<?xml ..."), Person.class);
Andrejs
sumber
1
Ini harus menjadi jawaban yang diterima. Itu tidak terlalu rumit.
bobbel
Sangat sederhana. Saya setuju sepenuhnya, itu pasti jawaban yang diterima.
Afaria
5
Saya sebenarnya tidak setuju dengan komentar di atas. Ini tentu lebih mudah tetapi menciptakan konteks dengan cepat sehingga dapat memiliki dampak kinerja bahkan jika konteksnya akhirnya di-cache. Gunakan dengan hati-hati.
Crystark
Jadi apa alternatifnya jika kita ingin memberikan kelas kepada unmarshaller? Satu-satunya metode mengambil parameter (node, class) dan di sini kita memiliki sebuah string.
Charles Follet
Dengan versi ringkas ini saya tidak menerima kesalahan penguraian, berguna untuk men-debug konfigurasi. Mungkin aku kehilangan sesuatu ...
berang
21

Tidak ada unmarshal(String)metode. Anda harus menggunakan Reader:

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

Tetapi biasanya Anda mendapatkan string itu dari suatu tempat, misalnya file. Jika itu masalahnya, lebih baik lewati saja FileReader.

Bozho
sumber
3

Jika Anda sudah memiliki xml, dan datang lebih dari satu atribut, Anda dapat menanganinya sebagai berikut:

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

metode getCharacterDataFromElement adalah

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

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