Użyj JAXB, aby utworzyć obiekt z ciągu XML

174

Jak mogę użyć poniższego kodu, aby usunąć ciąg XML z kodu XML i zamapować go na obiekt JAXB poniżej?

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
źródło

Odpowiedzi:

282

Aby przekazać zawartość XML, musisz zawinąć zawartość w a Reader, a zamiast tego nieważne:

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

StringReader reader = new StringReader("xml string here");
Person person = (Person) unmarshaller.unmarshal(reader);
skaffman
źródło
6
Czy możesz rozszerzyć tę odpowiedź, aby uwzględnić, jeśli „ciąg xml tutaj” zawiera kopertę SOAP?
JWiley
co by było, gdybyś chciał użyć Readerkombinacji z określoną klasą fasoli? Ponieważ nie ma unmarshall(Reader, Class)metody. Na przykład czy jest jakiś sposób, aby przekonwertować Readerdo javax.xml.transform.Source?
bvdb
2
W moim przypadku pracuj jako:JAXBElement<MyObject> elemento = (JAXBElement<MyObject>)unmarshaller.unmarshal(reader); MyObject object = elemento.getValue();
Cesar Miguel
1
@bvdb Można użyć javax.xml.transform.stream.StreamSourcektóra ma konstruktorów, które mają Reader, Filelub InputStream.
Muhd
Dzięki! W moim przypadku musiałem zrobić trochę inaczej: Person person = (Person) ((JAXBElement) unmarshaller.unmarshal (reader)). GetValue ();
Gustavo Amaro
161

Lub jeśli chcesz prosty, jednoliniowy:

Person person = JAXB.unmarshal(new StringReader("<?xml ..."), Person.class);
Andrejs
źródło
1
To powinna być akceptowana odpowiedź. To trochę mniej skomplikowane.
bobbel
Bardzo prosty. Całkowicie się zgadzam, to musi być zaakceptowana odpowiedź.
Afaria
5
Właściwie nie zgadzam się z powyższymi komentarzami. Z pewnością jest to łatwiejsze, ale tworzy kontekst w locie, więc może mieć wpływ na wydajność, nawet jeśli kontekst zostanie zapisany w pamięci podręcznej. Używaj ostrożnie.
Crystark
Jaka jest więc alternatywa, jeśli chcemy zapewnić lekcję nieważnemu? Jedyna metoda przyjmuje parametr (węzeł, klasa) i tutaj mamy łańcuch.
Charles Follet,
W tej zwięzłej wersji nie otrzymuję błędów analizy, przydatnych do debugowania konfiguracji. Pewnie czegoś mi brakuje ...
bóbr
21

Nie ma unmarshal(String)metody. Powinieneś użyć Reader:

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

Ale zwykle otrzymujesz ten ciąg skądś, na przykład plik. Jeśli tak jest, lepiej podaj FileReadersamo.

Bozho
źródło
3

Jeśli masz już xml i masz więcej niż jeden atrybut, możesz to zrobić w następujący sposób:

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

metoda getCharacterDataFromElement to

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

return cd.getData();
}
return "";
}
Miguel Zapata
źródło