Use JAXB para crear objetos a partir de cadenas XML

174

¿Cómo puedo usar el siguiente código para desarmar una cadena XML y asignarla al objeto JAXB a continuación?

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
fuente

Respuestas:

282

Para pasar contenido XML, debe envolver el contenido en un Reader, y desmarcar eso en su lugar:

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

StringReader reader = new StringReader("xml string here");
Person person = (Person) unmarshaller.unmarshal(reader);
skaffman
fuente
66
¿Podría ampliar esta respuesta para incluir si la "cadena xml aquí" incluye un sobre SOAP?
JWiley
¿Qué pasaría si quisiera usar una Readercombinación con una clase de bean específica? Ya que no hay unmarshall(Reader, Class)método. Por ejemplo, ¿hay alguna manera de convertir el Readera a javax.xml.transform.Source?
bvdb
2
En mi caso trabajo como:JAXBElement<MyObject> elemento = (JAXBElement<MyObject>)unmarshaller.unmarshal(reader); MyObject object = elemento.getValue();
Cesar Miguel
1
@bvdb Puede usar javax.xml.transform.stream.StreamSourceque tiene constructores que toman Reader, Fileo InputStream.
Muhd
¡Gracias! En mi caso, necesitaba hacer un poco diferente: Person person = (Person) ((JAXBElement) unmarshaller.unmarshal (reader)). GetValue ();
Gustavo Amaro
161

O si quieres una línea simple:

Person person = JAXB.unmarshal(new StringReader("<?xml ..."), Person.class);
Andrejs
fuente
1
Esta debería ser la respuesta aceptada. Eso es un poco menos complicado.
bobbel
Muy simple. Estoy totalmente de acuerdo, debe ser la respuesta aceptada.
Afaria
55
De hecho, no estoy de acuerdo con los comentarios anteriores. Ciertamente es más fácil, pero crea el contexto sobre la marcha para que pueda tener un impacto en el rendimiento, incluso si el contexto termina en caché. Usar con precaución.
Crystark
Entonces, ¿cuál es la alternativa si queremos proporcionar una clase para el desmonteador? El único método toma un parámetro (nodo, clase) y aquí tenemos una cadena.
Charles Follet
Con esta versión concisa no recibo errores de análisis, útiles para depurar una configuración. Probablemente me estoy perdiendo algo ...
castor
21

No hay unmarshal(String)método Debe usar un Reader:

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

Pero generalmente obtienes esa cadena de algún lugar, por ejemplo, un archivo. Si ese es el caso, mejor pasa el FileReadersí mismo.

Bozho
fuente
3

Si ya tiene el xml y viene con más de un atributo, puede manejarlo de la siguiente manera:

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

el método getCharacterDataFromElement es

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

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