2012-12-18 14 views
9

mam schematu, który określa następujące rodzaje:Szeregowania z JAXB i Dowolna

<xsd:complexType name="Payload"> 
    <xsd:sequence> 
     <xsd:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax"/> 
    </xsd:sequence> 
</xsd:complexType> 

I to tworzy obiekt tak:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "Payload", propOrder = { 
    "any" 
}) 
public class Payload { 

    @XmlAnyElement(lax = true) 
    protected List<Object> any; 
} 

Teraz próbuję dodać kolejny wygenerowany obiekt JAXB do Ładunek, który robi coś takiego:

Class payloadClass = ...; 
JAXBContext context = JAXBContext.newInstance(WrapperRequest.class, payloadClass); 
... 
marshaller.marshal(wrappedRequest); 

Ale mam straszny wyjątek, który wygląda jak to będzie nigdy wor k więc decyduję się najpierw serializować obiekt ładunku na XML, a następnie dodać go jako ciąg znaków w polu danych.

StringWriter writer = new StringWriter(); 
JAXBContext context = JAXBContext.newInstance(sdoRequest.getClass()); 
Marshaller marshaller = context.createMarshaller(); 
marshaller.marshal(new JAXBElement(new QName("uri", sdoRequest.getClass().getSimpleName()), sdoRequest.getClass(), sdoRequest), writer); 
payload.getAny().add(writer.toString()); 

A to wysadza się z wyjątkiem, mówiąc "java.lang.String" nie zawiera @XmlRootElement.

Jak zatem korzystać z xs: kiedykolwiek współpracować z JAXB? Wydaje się, że nic nie chce działać, ponieważ JAXB zmienia ładunek w obiekt i nie będzie serializować niczego w Object. To wszystko jest również w Axis2, więc dotarcie do tego punktu było bardzo trudne.

+1

Jakiego wyjątku otrzymujesz, próbując dodać zawinięty obiekt do dowolnego ładunku danych? – gregwhitaker

+1

Poniższe informacje powinny pomóc: http://blog.bdoughan.com/2010/08/using-xmlanyelement-to-build-generic.html –

+0

Częściowo w jaki sposób tworzone są WSDL, na które mam zerową kontrolę. Jednak żądanie opakowywania jest zdefiniowane w jednym pliku WSDL, a żądanie w polu danych jest zdefiniowane w innym pliku WSDL. Obaj deklarują BaseRequest, ale kiedy generowany jest kod, są to różne klasy. I otrzymuję ten wyjątek Dwie klasy mają tę samą nazwę typu XML {http://esp.lala.com/2012/eo}BaseRequest. Użyj @ XmlType.name i @ XmlType.namespace, aby przypisać im różne nazwy. – chubbsondubs

Odpowiedz

14

Poniżej wykażę JAXB (JSR-222) i any na przykładzie:

Ładowność

Obiekt any jest opatrzone @XmlAnyElement(lax=true). Oznacza to, że dla tej właściwości, jeśli element jest powiązany z klasą za pomocą @XmlRootElement lub @XmlElementDecl, wówczas instancja odpowiedniego obiektu zostanie użyta do zapełnienia właściwości, jeśli nie, element zostanie ustawiony jako instancja org.w3c.dom.Element.

package forum13941747; 

import java.util.List; 
import javax.xml.bind.annotation.*; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "Payload", propOrder = { 
    "any" 
}) 
public class Payload { 

    @XmlAnyElement(lax = true) 
    protected List<Object> any; 

} 

Foo

Poniżej jest przykład klasy adnotacjami z @XmlRootElement.

package forum13941747; 

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Foo { 

} 

Bar

Poniżej jest przykład klasy bez @XmlRootElement adnotacji. W tym przypadku użyjemy adnotacji @XmlElementDecl na klasie fabrycznej (zwykle o nazwie ObjectFactory) z przypisami @XmlRegistry.

package forum13941747; 

public class Bar { 

} 

ObjectFactory

Poniżej jest przykład określając @XmlElementDecl adnotacji dla klasy Bar.

package forum13941747; 

import javax.xml.bind.JAXBElement; 
import javax.xml.bind.annotation.*; 
import javax.xml.namespace.QName; 

@XmlRegistry 
public class ObjectFactory { 

    @XmlElementDecl(name="bar") 
    public JAXBElement<Bar> createBar(Bar bar) { 
     return new JAXBElement<Bar>(new QName("bar"), Bar.class, bar); 
    } 

} 

input.xml

Poniżej znajduje się dokument wejściowy użyjemy do tego przykładu. Istnieją 3 elementy, które odpowiadają właściwości any.Pierwsza odpowiada adnotacji @XmlRootElement w klasie Foo. Druga odpowiada adnotacji @XmlElementDecl dla klasy Bar, a trzecia nie odpowiada żadnej z klas domeny.

<?xml version="1.0" encoding="UTF-8"?> 
<payload> 
    <foo/> 
    <bar/> 
    <other/> 
</payload> 

Demo

W kodzie demo poniżej będziemy unmarshal dokumentu wejściowego, a następnie wyjście klas obiektów w otrzymanej any własności, a następnie zebrać przedmiot payload z powrotem do XML.

package forum13941747; 

import java.io.File; 
import javax.xml.bind.*; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Payload.class, Foo.class, ObjectFactory.class); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("src/forum13941747/input.xml"); 
     Payload payload = (Payload) unmarshaller.unmarshal(xml); 

     for(Object o : payload.any) { 
      System.out.println(o.getClass()); 
     } 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(payload, System.out); 
    } 

} 

Wyjście

Poniżej jest wyjście z uruchomieniem kodu demo. Zwróć uwagę na klasy odpowiadające obiektom we właściwości any. Element foo stał się instancją klasy Foo. Element bar stał się instancją JAXBElement, która zawiera instancję Bar. Element other stał się instancją org.w3c.dom.Element.

class forum13941747.Foo 
class javax.xml.bind.JAXBElement 
class com.sun.org.apache.xerces.internal.dom.ElementNSImpl 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<payload> 
    <foo/> 
    <bar/> 
    <other/> 
</payload> 
1

Wykorzystaj Object Factory dla mashelling obiektu jak poniżej ciebie nie trzeba mieć @XmlRootElement w DemoType.java.,

DemoType demoServiceRequest = new DemoType(); 
ObjectFactory obDemo = new ObjectFactory(); 
Request requestObject = new Request();  
requestObject.setAny(obDemo.createDemo(demoServiceRequest)); 

I dodać klasę DemoType na Request.java jak @XmlSeeAlso ({DemoType.class})