[英]Serializing with JAXB and the Any
我有一個定義以下類型的模式:
<xsd:complexType name="Payload">
<xsd:sequence>
<xsd:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xsd:sequence>
</xsd:complexType>
這會創建一個像這樣的對象:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Payload", propOrder = {
"any"
})
public class Payload {
@XmlAnyElement(lax = true)
protected List<Object> any;
}
現在我嘗試將另一個生成的JAXB對象添加到該Payload,執行以下操作:
Class payloadClass = ...;
JAXBContext context = JAXBContext.newInstance( WrapperRequest.class, payloadClass);
...
marshaller.marshal( wrappedRequest );
但是我得到了一個可怕的異常,看起來它永遠不會工作所以我決定先將有效負載對象序列化為XML,然后將其作為字符串添加到有效負載中。
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() );
這會引發異常,說“java.lang.String”不包含@XmlRootElement。
那么如何使用xs:任何使用過的JAXB? 似乎沒有什么可以工作,因為JAXB將Payload轉換為Object,並且它不會僅對Object中的任何內容進行序列化。 這一切都在Axis2內部,因此達到這一點非常具有挑戰性。
下面我將演示JAXB(JSR-222)以及any
一個示例:
有效載荷
any
屬性使用@XmlAnyElement(lax=true)
注釋@XmlAnyElement(lax=true)
。 這意味着對於該屬性,如果元素通過@XmlRootElement
或@XmlElementDecl
與類關聯,則相應對象的實例將用於填充屬性,否則該元素將被設置為org.w3c.dom.Element
的實例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;
}
富
下面是使用@XmlRootElement
注釋的類的示例。
package forum13941747;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Foo {
}
酒吧
下面是沒有@XmlRootElement
注釋的類的@XmlRootElement
。 在這個用例,我們將充分利用@XmlElementDecl
在工廠類(通常稱為注釋ObjectFactory
帶注釋) @XmlRegistry
。
package forum13941747;
public class Bar {
}
的ObjectFactory
下面是為Bar
類指定@XmlElementDecl
注釋的示例。
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中
下面是我們將用於此示例的輸入文檔。 有3個元素對應於any
屬性。 第一個對應於Foo
類上的@XmlRootElement
注釋。 第二個對應於Bar
類的@XmlElementDecl
注釋,第三個對應於任何域類。
<?xml version="1.0" encoding="UTF-8"?>
<payload>
<foo/>
<bar/>
<other/>
</payload>
演示
在下面的演示代碼中,我們將解組輸入文檔,然后在生成的any
屬性中輸出對象的類,然后將payload
對象封送回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);
}
}
產量
以下是運行演示代碼的輸出。 請注意與any
屬性中的對象相對應的類。 foo
元素成為Foo
類的一個實例。 bar
元素成為JAXBElement
一個實例,它包含一個Bar
實例。 other
元素成為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>
利用Object Factory來設置對象,如下所示,你不需要在DemoType.java中使用@XmlRootElement。
DemoType demoServiceRequest = new DemoType();
ObjectFactory obDemo = new ObjectFactory();
Request requestObject = new Request();
requestObject.setAny(obDemo.createDemo(demoServiceRequest));
並在Request.java中添加DemoType類,如@XmlSeeAlso({DemoType.class})
如果您的有效負載是XML字符串,我設法使用以下代碼解決同樣的問題:
import javax.xml.parsers.DocumentBuilderFactory;
//...
String XMLPAYLOAD = "...";
Payload payload = new ObjectFactory().createPayload();
try {
payload.setAny(DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(new InputSource(new StringReader(XMLPAYLOAD)))
.getDocumentElement());
} catch (Exception e) {
e.printStackTrace();
}
//...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.