我试图从FpML(金融产品标记语言)4.5版本生成Java类。生成了大量代码,但我无法使用它。试图序列化一个简单的文档,我得到这个:
javax.xml.bind.MarshalException
- with linked exception: [com.sun.istack.SAXException2: unable
to marshal type
"org.fpml._2008.fpml_4_5.PositionReport"
as an element because it is missing an
@XmlRootElement annotation]
事实上,没有任何类具有@XmlRootElement注释,所以我可能做错了什么?我将xjc (JAXB 2.1)指向fpml-main-4-5。Xsd,然后包括所有类型。
为了将其他人已经陈述或暗示的内容联系在一起,JAXB XJC决定是否将@XmlRootElement注释放在生成的类上的规则非常重要(请参阅本文)。
@XmlRootElement的存在是因为JAXB运行时需要某些信息才能封送/解封送给定对象,特别是XML元素名称和名称空间。你不能直接把任何旧对象传递给Marshaller。@XmlRootElement提供此信息。
然而,注释只是一种方便,JAXB并不需要它。另一种方法是使用JAXBElement包装器对象,它提供与@XmlRootElement相同的信息,但是以对象的形式,而不是注释的形式。
但是,JAXBElement对象构造起来很麻烦,因为您需要知道XML元素名称和名称空间,而业务逻辑通常不知道这些。
Thankfully, when XJC generates a class model, it also generates a class called ObjectFactory. This is partly there for backwards compatibility with JAXB v1, but it's also there as a place for XJC to put generated factory methods which create JAXBElement wrappers around your own objects. It handles the XML name and namespace for you, so you don't need to worry about it. You just need to look through the ObjectFactory methods (and for large schema, there can be hundreds of them) to find the one you need.
上面已经链接的博客文章底部提到了这一点,但这对我来说就像一种享受:
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(new JAXBElement<MyClass>(new QName("uri","local"), MyClass.class, myClassInstance), System.out);
您可以使用如何在XSD中为基类型生成@XmlRootElement类中的绑定来修复此问题。
下面是Maven的一个示例
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.3.1</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>src/main/resources/xsd</schemaDirectory>
<packageName>com.mycompany.schemas</packageName>
<bindingFiles>bindings.xjb</bindingFiles>
<extension>true</extension>
</configuration>
</plugin>
这是装订。XJB文件内容
<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc"
jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="path/to/myschema.xsd" node="/xs:schema">
<jxb:globalBindings>
<xjc:simple/>
</jxb:globalBindings>
</jxb:bindings>
</jxb:bindings>