unmarshal parse jaxbunmarshaller example convert java jaxb unmarshalling

java - parse - string unmarshal jaxb



DesasignaciĆ³n JAXB con java generics (1)

Estoy intentando separar un documento XML de un sistema heredado usando JAXB. Tengo una estructura xml de la siguiente manera:

<response> <id>000000</id> <results> <result> <!-- Request specific xml content --> <year>2003</year> <title>Lorem Ipsum</title> <items> <item>I1</item> <item>I2</item> </items> </result> <result> <year>2007</year> <title>Dolor sit amet</title> <items> <item>K1</item> <item>K2</item> </items> </result> </results> </response>

Las etiquetas dentro de la parte especificada por la etiqueta <result> cambiarán según mi solicitud. Dado que el contenido puede cambiar, decidí usar genéricos para los ítems de resultados y preparé mis frijoles java con anotaciones de la siguiente manera:

// imports here @XmlRootElement(name="response") @XmlAccessorType(XmlAccessType.FIELD) public class XResponse<T>{ private String id; @XmlElementWrapper(name="results") @XmlElement(name="result") private List<T> results; // setters and getters } ... @XmlRootElement(name="result") @XmlAccessorType(XmlAccessType.FIELD) public class X1Result{ private String year; private String title; @XmlElementWrapper(name="items") @XmlElement(name="item") private List<String> items; // setters and getters } ...

Traté de desasignar el documento xml a través del siguiente código:

JAXBContext context = JAXBContext.newInstance(XResponse.class, X1Result.class); Unmarshaller um = context.createUnmarshaller(); XResponse<X1Result> response = (XResponse<X1Result>) um.unmarshal( xmlContent ); List<X1Result> results = unmarshal.getResults(); for (X1Result object : results) { System.out.println(object.getClass()); }

Tengo un problema durante el desemparejamiento que no puede convertir los elementos de la lista en la clase X1Result . En su lugar, utiliza org.apache.xerces.dom.ElementNSImpl .

¿Qué debo hacer para que JAXB Unmarshaller use la clase X1Result ?

Gracias por adelantado


Creo que deberías usar herencia en lugar de genéricos. Dado un XML como este:

<?xml version="1.0" encoding="UTF-8"?> <response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <id>000000</id> <results> <result xsi:type="X1Result"> <year>2003</year> <title>Lorem Ipsum</title> <items> <item>I1</item> <item>I2</item> </items> </result> <result xsi:type="X1Result"> <year>2007</year> <title>Dolor sit amet</title> <items> <item>K1</item> <item>K2</item> </items> </result> </results> </response>

Puede vincular dinámicamente sus entradas de <result> . Tienes un tipo de nivel superior:

@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "XResult") @XmlSeeAlso({ X1Result.class })public abstract class XResult { }

Y tienes clases implementadas:

@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "X1Result") public class X1Result extends XResult { @XmlElement(name = "year") private String year; @XmlElement(name = "title") private String title; @XmlElementWrapper(name = "items") @XmlElement(name = "item") private List<String> items; ... }

Use el tipo de nivel superior en su clase XResponse:

@XmlRootElement(name = "response") @XmlAccessorType(XmlAccessType.FIELD) public class XResponse { @XmlElement(name = "id") private String id; @XmlElementWrapper(name = "results") @XmlElement(name = "result") private List<XResult> results; ... }

Y puede deshacerse usando el tipo de nivel superior:

context = JAXBContext.newInstance(XResponse.class, XResult.class); Unmarshaller unmarshaller = context.createUnmarshaller(); XResponse response = (XResponse) unmarshaller.unmarshal(new File("testfile.xml")); List<XResult> results = response.getResults(); for (XResult object : results) { System.out.println(object.getClass()); }