2012-12-18 33 views
9

Tôi có một schema định nghĩa các loại sau đây:Serializing với JAXB và Bất kỳ

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

Và đó tạo ra một đối tượng như vậy:

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

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

Bây giờ tôi cố gắng thêm một tạo vật JAXB có trách nhiệm Payload thực hiện một việc như sau:

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

Nhưng tôi nhận được ngoại lệ khủng khiếp có vẻ như sẽ không bao giờ k vì vậy tôi quyết định tuần tự hóa đối tượng tải trọng thành XML trước, sau đó thêm nó làm chuỗi trong tải trọng.

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

Và điều này xảy ra với ngoại lệ cho biết "java.lang.String" không chứa @XmlRootElement.

Vậy cách sử dụng xs: bất kỳ khi nào hoạt động với JAXB? Không có gì có vẻ muốn làm việc vì JAXB biến Payload thành Object, và nó sẽ không tuần tự hóa bất cứ thứ gì trong Object. Đây là tất cả bên trong Axis2 vì vậy rất khó để có được đến thời điểm này.

+1

Bạn nhận được ngoại lệ nào khi bạn cố gắng thêm đối tượng được bao bọc vào bất kỳ Tải trọng nào? – gregwhitaker

+1

Sau đây sẽ giúp: http://blog.bdoughan.com/2010/08/using-xmlanyelement-to-build-generic.html –

+0

Đây là một phần cách các WSDL được đặt cùng nhau mà tôi không kiểm soát được. Tuy nhiên, yêu cầu gói được định nghĩa trong một WSDL và yêu cầu đi trong tải trọng được định nghĩa trong một WSDL khác. Cả hai đều khai báo một BaseRequest, nhưng khi mã được tạo ra thì chúng là các lớp khác nhau. Và tôi nhận được ngoại lệ này Hai lớp có cùng tên kiểu XML {http://esp.lala.com/2012/eo}BaseRequest. Sử dụng @ XmlType.name và @ XmlType.namespace để gán các tên khác nhau cho chúng. – chubbsondubs

Trả lời

14

Dưới đây tôi sẽ chứng minh JAXB (JSR-222)any với một ví dụ:

Payload

Thuộc tính any được chú thích với @XmlAnyElement(lax=true). Điều này có nghĩa là đối với thuộc tính đó nếu một phần tử được liên kết với một lớp thông qua @XmlRootElement hoặc @XmlElementDecl thì một cá thể của đối tượng tương ứng sẽ được sử dụng để điền thuộc tính nếu không phải thành phần sẽ được đặt làm phiên bản 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

Dưới đây là một ví dụ về một lớp chú thích với @XmlRootElement.

package forum13941747; 

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Foo { 

} 

Bar

Dưới đây là một ví dụ về một lớp học mà không có sự @XmlRootElement chú thích. Trong trường hợp sử dụng này, chúng tôi sẽ tận dụng chú thích @XmlElementDecl trên một lớp nhà máy (thường được gọi là ObjectFactory) được chú thích với @XmlRegistry.

package forum13941747; 

public class Bar { 

} 

ObjectFactory

Dưới đây là một ví dụ về cách xác định một chú thích @XmlElementDecl cho lớp 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

Dưới đây là tài liệu đầu vào, chúng tôi sẽ sử dụng cho ví dụ này. Có 3 phần tử tương ứng với thuộc tính any.Chữ cái đầu tiên tương ứng với chú thích @XmlRootElement trên lớp Foo. Cột thứ hai tương ứng với chú thích @XmlElementDecl cho lớp Bar và chú thích thứ ba không tương ứng với bất kỳ lớp miền nào.

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

Demo

Trong code demo dưới đây chúng tôi sẽ unmarshal tài liệu đầu vào, sau đó sản lượng các lớp học của các đối tượng trong kết quả any tài sản và sau đó sắp xếp các đối tượng payload trở về 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); 
    } 

} 

Output

Dưới đây là sản phẩm chạy mã demo. Lưu ý các lớp tương ứng với các đối tượng trong thuộc tính any. Phần tử foo đã trở thành một phiên bản của lớp Foo. Phần tử bar đã trở thành một phiên bản của JAXBElement chứa một phiên bản Bar. Phần tử other đã trở thành một phiên bản của 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

Make sử dụng Nhà máy Object cho mashelling đối tượng như dưới đây bạn không cần phải có @XmlRootElement trong DemoType.java.,

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

Và thêm lớp DemoType tại Request.java như @XmlSeeAlso ({DemoType.class})