Use JAXB para criar objetos a partir de XML String

174

Como posso usar o código abaixo para cancelar a distribuição de uma string XML e mapeá-la para o objeto JAXB abaixo?

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
fonte

Respostas:

282

Para passar o conteúdo XML, você precisa agrupar o conteúdo em a Readere unshalshal que:

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

StringReader reader = new StringReader("xml string here");
Person person = (Person) unmarshaller.unmarshal(reader);
skaffman
fonte
6
Você poderia expandir esta resposta para incluir se a "sequência xml aqui" inclui um envelope SOAP?
JWiley
e se você quisesse usar um Readerem combinação com uma classe de bean específica? Como não há unmarshall(Reader, Class)método. Por exemplo, existe uma maneira de converter o Readerpara um javax.xml.transform.Source?
bvdb
2
No meu caso, trabalho como:JAXBElement<MyObject> elemento = (JAXBElement<MyObject>)unmarshaller.unmarshal(reader); MyObject object = elemento.getValue();
Cesar Miguel
1
@bvdb Você pode usar javax.xml.transform.stream.StreamSourceque tem construtores que levam Reader, Fileou InputStream.
Muhd
Obrigado! No meu caso, eu precisava fazer um pouco diferente: Person person = (Person) ((JAXBElement) unmarshaller.unmarshal (reader)). GetValue ();
Gustavo Amaro
161

Ou se você quiser uma única linha:

Person person = JAXB.unmarshal(new StringReader("<?xml ..."), Person.class);
Andrejs
fonte
1
Essa deve ser a resposta aceita. Isso é um pouco menos complicado.
bobbel
Muito simples. Eu concordo totalmente, deve ser a resposta aceita.
Afaria
5
Na verdade, eu discordo dos comentários acima. Certamente é mais fácil, mas cria o contexto em tempo real para ter impactos no desempenho, mesmo que o contexto acabe sendo armazenado em cache. Use com cuidado.
Crystark 2/02
Então, qual é a alternativa se queremos fornecer uma classe para o não-agente? O único método leva um (nó, classe) no parâmetro e aqui temos uma string.
Charles Follet
Com esta versão concisa, não recebo erros de análise, úteis para depurar uma configuração. Provavelmente eu estou faltando alguma coisa ...
castor
21

Não existe unmarshal(String)método. Você deve usar um Reader:

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

Mas geralmente você está obtendo essa string de algum lugar, por exemplo, um arquivo. Se for esse o caso, é melhor passar por FileReadersi.

Bozho
fonte
3

Se você já possui o xml e vem com mais de um atributo, é possível lidar com ele da seguinte maneira:

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

o método getCharacterDataFromElement é

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

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