问题描述
我有一个定义以下类型的模式:
I have a schema that defines the following type:
<xsd:complexType name="Payload">
<xsd:sequence>
<xsd:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xsd:sequence>
</xsd:complexType>
这会创建一个如下对象:
And that creates an object like so:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Payload", propOrder = {
"any"
})
public class Payload {
@XmlAnyElement(lax = true)
protected List<Object> any;
}
现在我尝试将另一个生成的JAXB对象添加到该Payload,执行以下操作:
Now I try adding another generated JAXB object to that Payload doing something like this:
Class payloadClass = ...;
JAXBContext context = JAXBContext.newInstance( WrapperRequest.class, payloadClass);
...
marshaller.marshal( wrappedRequest );
但我得到一个可怕的异常,看起来它永远不会工作所以我决定序列化有效载荷首先将对象添加到XML中,然后将其作为字符串添加到有效负载中。
But I get a terrible exception that looks like it'll never work so I decide to serialize the payload object to XML first then add that as a string in the payload.
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 。
And this blows up with an exception saying "java.lang.String" does not contain an @XmlRootElement.
那么使用xs:如何使用JAXB?似乎没有什么可以工作,因为JAXB将Payload转换为Object,并且它不会仅仅对Object中的任何内容进行序列化。这一切都在Axis2内部,所以要达到这一点是非常具有挑战性的。
So how will the use of xs:any ever work with JAXB? Nothing seems to want to work because JAXB turns the Payload into Object, and it won't serialize just anything in Object. This is all inside Axis2 as well so it's been very challenging to get to this point.
推荐答案
下面我将演示和任何
举个例子:
Below I will demonstrate JAXB (JSR-222) and any
with an example:
有效负载
任何
属性都使用 @XmlAnyElement(lax = true)
进行注释。这意味着对于该属性,如果元素通过 @XmlRootElement
或 @XmlElementDecl
与一个类相关联,那么如果不将元素设置为 org.w3c.dom.Element
的实例,则使用相应的对象来填充属性。
The any
property is annotated with @XmlAnyElement(lax=true)
. This means that for that property if an element is associated with a class via @XmlRootElement
or @XmlElementDecl
then an instance of the corresponding object will be used to populate the property if not the element will be set as an instance of 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
以下是使用 @XmlRootElement
注释的类的示例。
Below is an example of a class annotated with @XmlRootElement
.
package forum13941747;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Foo {
}
Bar
以下是没有 @XmlRootElement $ c的类的示例$ c>注释。在这个用例中,我们将利用<$注释的工厂类(通常称为
。 ObjectFactory
)利用 @XmlElementDecl
注释。 c $ c> @XmlRegistry
Below is an example of a class without the @XmlRootElement
annotation. In this use case we will leverage the @XmlElementDecl
annotation on a factory class (usually called ObjectFactory
) annotated with @XmlRegistry
.
package forum13941747;
public class Bar {
}
ObjectFactory
以下是为<$指定 @XmlElementDecl
注释的示例c $ c> Bar class。
Below is an example of specifying an @XmlElementDecl
annotation for the Bar
class.
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个元素对应任何
属性。第一个对应于 Foo
类中的 @XmlRootElement
注释。第二个对应于 Bar
类的 @XmlElementDecl
注释,第三个对应于任何域类。
Below is the input document we'll use for this example. There are 3 elements that correspond to the any
property. The first corresponds to the @XmlRootElement
annotation on the Foo
class. The second corresponds to the @XmlElementDecl
annotation for the Bar
class and the third does not correspond to any of the domain classes.
<?xml version="1.0" encoding="UTF-8"?>
<payload>
<foo/>
<bar/>
<other/>
</payload>
演示
在下面的演示代码中,我们将解组输入文档,然后在结果任何
属性中输出对象的类,然后封送有效负载
对象返回XML。
In the demo code below we will unmarshal the input document, then output the classes of the objects in the resulting any
property and then marshal the payload
object back to 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 $ c的实例$ C>。
其他
元素成为 org.w3c.dom.Element
的实例。
Below is the output from running the demo code. Note the classes corresponding to the objects in the any
property. The foo
element became an instance of the Foo
class. The bar
element became an instance of JAXBElement
that holds an instance of Bar
. The other
element became an instance of 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>
这篇关于使用JAXB和Any进行序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!