使用JAXB和Any进行序列化

chu*_*ubs 10 java xsd axis2 jaxb

我有一个定义以下类型的模式:

<xsd:complexType name="Payload">
   <xsd:sequence>
      <xsd:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
   </xsd:sequence>
</xsd:complexType>
Run Code Online (Sandbox Code Playgroud)

这会创建一个像这样的对象:

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

    @XmlAnyElement(lax = true)
    protected List<Object> any;
}
Run Code Online (Sandbox Code Playgroud)

现在我尝试将另一个生成的JAXB对象添加到该Payload,执行以下操作:

Class payloadClass = ...;
JAXBContext context = JAXBContext.newInstance( WrapperRequest.class, payloadClass);
...
marshaller.marshal( wrappedRequest );
Run Code Online (Sandbox Code Playgroud)

但是我得到一个可怕的异常看起来它永远不会工作所以我决定先将有效负载对象序列化为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() );
Run Code Online (Sandbox Code Playgroud)

这会引发异常,说"java.lang.String"不包含@XmlRootElement.

那么如何使用xs:任何使用过的JAXB?似乎没有什么可以工作,因为JAXB将Payload转换为Object,并且它不会仅对Object中的任何内容进行序列化.这一切都在Axis2内部,因此达到这一点非常具有挑战性.

bdo*_*han 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;

}
Run Code Online (Sandbox Code Playgroud)

下面是一个带注释的类的示例@XmlRootElement.

package forum13941747;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Foo {

}
Run Code Online (Sandbox Code Playgroud)

酒吧

下面是没有@XmlRootElement注释的类的示例.在这个用例中,我们将利用@XmlElementDecl注释的工厂类(通常称为ObjectFactory)上的注释@XmlRegistry.

package forum13941747;

public class Bar {

}
Run Code Online (Sandbox Code Playgroud)

的ObjectFactory

下面是@XmlElementDeclBar类指定注释的示例.

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

}
Run Code Online (Sandbox Code Playgroud)

input.xml中

下面是我们将用于此示例的输入文档.有3个元素对应于any属性.第一个对应于类的@XmlRootElement注释Foo.第二个对应于类的@XmlElementDecl注释,Bar第三个对应于任何域类.

<?xml version="1.0" encoding="UTF-8"?>
<payload>
    <foo/>
    <bar/>
    <other/>
</payload>
Run Code Online (Sandbox Code Playgroud)

演示

在下面的演示代码中,我们将解组输入文档,然后在结果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);
    }

}
Run Code Online (Sandbox Code Playgroud)

产量

以下是运行演示代码的输出.请注意与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>
Run Code Online (Sandbox Code Playgroud)