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

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

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

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.


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 "";
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.