没有由 JAXB 生成的 @XmlRootElement

2022-01-19 00:00:00 java jaxb xjc fpml

我正在尝试从 FpML(金融产品标记语言)4.5 版生成 Java 类.生成了大量代码,但我无法使用它.试图序列化一个简单的文档,我得到了这个:

I'm trying to generate Java classes from the FpML (Finanial Products Markup Language) version 4.5. A ton of code is generated, but I cannot use it. Trying to serialize a simple document I get this:

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]

事实上 no 类有 @XmlRootElement 注释,所以我做错了什么?我将 xjc (JAXB 2.1) 指向 fpml-main-4-5.xsd,然后包含所有类型.

In fact no classses have the @XmlRootElement annotation, so what can I be doing wrong?. I'm pointing xjc (JAXB 2.1) to fpml-main-4-5.xsd, which then includes all types.

推荐答案

将其他人已经说过或暗示过的东西结合起来,JAXB XJC 决定是否放置 @XmlRootElement 生成的类上的注释很重要(见这篇文章).

To tie together what others have already stated or hinted at, the rules by which JAXB XJC decides whether or not to put the @XmlRootElement annotation on a generated class are non trivial (see this article).

@XmlRootElement 存在是因为 JAXB 运行时需要某些信息来编组/解组给定对象,特别是 XML 元素名称和命名空间.您不能将任何旧对象传递给 Marshaller.@XmlRootElement 提供此信息.

@XmlRootElement exists because the JAXB runtime requires certain information in order to marshal/unmarshal a given object, specifically the XML element name and namespace. You can't just pass any old object to the Marshaller. @XmlRootElement provides this information.

注解只是为了方便,但是 - JAXB 不需要它.替代方法是使用 JAXBElement 包装器对象,它提供与 @XmlRootElement 相同的信息,但采用对象的形式,而不是注释.

The annotation is just a convenience, however - JAXB does not require it. The alternative to is to use JAXBElement wrapper objects, which provide the same information as @XmlRootElement, but in the form of an object, rather than an annotation.

但是,JAXBElement 对象很难构造,因为您需要知道 XML 元素名称和命名空间,而业务逻辑通常不需要.

However, JAXBElement objects are awkward to construct, since you need to know the XML element name and namespace, which business logic usually doesn't.

幸运的是,当 XJC 生成一个类模型时,它也生成了一个名为 ObjectFactory 的类.这部分是为了向后兼容 JAXB v1,但它也是 XJC 放置生成的工厂方法的地方,这些方法在您自己的对象周围创建 JAXBElement 包装器.它为您处理 XML 名称和命名空间,因此您无需担心.您只需查看 ObjectFactory 方法(对于大型架构,可能有数百个)找到您需要的方法.

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.

相关文章