我有一个定义以下类型的模式:
<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中,所以要达到这一点是非常具有挑战性的。
答案 0 :(得分:17)
下面我将通过示例演示JAXB (JSR-222)和any
:
<强>有效载荷强>
any
属性注释为@XmlAnyElement(lax=true)
。这意味着对于该属性,如果元素通过@XmlRootElement
或@XmlElementDecl
与类关联,则相应对象的实例将用于填充属性,否则该元素将被设置为实例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
注释的类的示例。在这个用例中,我们将利用@XmlElementDecl
注释的工厂类(通常称为ObjectFactory
)来利用@XmlRegistry
注释。
package forum13941747;
public class Bar {
}
<强>的ObjectFactory 强>
以下是为@XmlElementDecl
类指定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中强>
以下是我们将用于此示例的输入文档。有3个元素对应any
属性。第一个对应@XmlRootElement
类的Foo
注释。第二个对应于@XmlElementDecl
类的Bar
注释,第三个对应于任何域类。
<?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>
答案 1 :(得分:1)
使用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})
答案 2 :(得分:0)
如果您的有效载荷是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();
}
//...