2012-10-05 14 views
6

Próbuję unmarshall dokument XML z dotychczasowego systemu przy użyciu JAXB. Mam struktury XML w następujący sposób:JAXB unmarshalling z java generics

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

Znaczniki wewnątrz części określonej przez <result> tag będzie się zmieniać w zależności moją prośbę. Ponieważ zawartość może zmienić postanowiłem wykorzystać rodzajowych dla pozycji wynikowych i przygotowałem moje fasoli java z adnotacjami w następujący sposób:

// 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 
} 
... 

Próbowałem unmarshalling dokumentu XML za pomocą poniższego kodu:

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

Podczas rozpakowywania mam problem z tym, że nie można przesyłać elementów listy do klasy X1Result. Zamiast tego używa org.apache.xerces.dom.ElementNSImpl.

Co należy zrobić, aby JAXB Unmarshaller korzystał z klasy X1Result?

Dzięki z góry

Odpowiedz

2

myślę, że należy użyć dziedziczenia zamiast generycznych. Podany kod XML wygląda tak:

<?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> 

Możesz dynamicznie wiązać swoje wpisy <result>. Masz typu top-level:

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

} 

I masz zajęcia wykonawcze:

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

użyć typu najwyższego poziomu w swojej klasie 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; 
    ... 
} 

I można wycofać przy użyciu typu najwyższego poziomu:

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

Powyższy kod ializes 'XResult' zamiast' X1Result' i dlatego daje błąd, ponieważ jest klasą abstrakcyjną. Poza tym zawartość xml pochodzi z dotychczasowego systemu i nie ma dostępnych informacji typu "xsi: type". (chociaż mogę go dodać programowo) – Alper

+0

Kod stworzy instancję 'X1Result', jeśli jest tam' 'xsi: type'. Przynajmniej tak to dla mnie działa. Powodzenia. – davidfmatheson

+0

To działało dobrze dla mnie bez 'xsi: type' obecnego w XML. Używam Java 1.7.0_15. –

Powiązane problemy