我试图从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,然后包括所有类型。


当前回答

这对我们也没用。但我们确实找到了一篇被广泛引用的文章,增加了一些背景……我将在这里链接到它,以方便下一个人:http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html

其他回答

上面已经链接的博客文章底部提到了这一点,但这对我来说就像一种享受:

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吗?

<!-- create-logical-system -->
<xs:element name="methodCall">
  <xs:complexType>
    ...
  </xs:complexType>
</xs:element>

@XmlRootElement不需要解组-如果使用2参数形式的Unmarshaller#unmarshall。

所以,如果不这样做:

UserType user = (UserType) unmarshaller.unmarshal(new StringReader(responseString));

一个人应该做:

JAXBElement<UserType> userElement = unmarshaller.unmarshal(someSource, UserType.class);
UserType user = userElement.getValue();

后一种代码将不需要UserType类级别的@XmlRootElement注释。

正如上面的答案之一所暗示的,如果在XSD中根元素的类型定义为命名类型,则根元素上不会有XMLRootElement,因为该命名类型可以在XSD中的其他地方使用。尝试将其转换为匿名类型,即:

<xsd:element name="myRootElement" type="MyRootElementType" />

<xsd:complexType name="MyRootElementType">
...
</xsd:complexType>

你会:

<xsd:element name="myRootElement">
    <xsd:complexType>
    ...
    <xsd:complexType>
</xsd:element>

Joe's answer (Joe Jun 26 '09 at 17:26) does it for me. The simple answer is that absence of an @XmlRootElement annotation is no problem if you marshal a JAXBElement. The thing that confused me is the generated ObjectFactory has 2 createMyRootElement methods - the first takes no parameters and gives the unwrapped object, the second takes the unwrapped object and returns it wrapped in a JAXBElement, and marshalling that JAXBElement works fine. Here's the basic code I used (I'm new to this, so apologies if the code's not formatted correctly in this reply), largely cribbed from link text:

ObjectFactory objFactory = new ObjectFactory();
MyRootElement root = objFactory.createMyRootElement();
...
// Set root properties
...
if (!writeDocument(objFactory.createMyRootElement(root), output)) {
    System.err.println("Failed to marshal XML document");
}
...

private boolean writeDocument(JAXBElement document, OutputStream output) {

  Class<?> clazz = document.getValue().getClass();
  try {
    JAXBContext context =
        JAXBContext.newInstance(clazz.getPackage().getName());
    Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    m.marshal(document, output);
    return true;

  } catch (JAXBException e) {
    e.printStackTrace(System.err);
    return false;
  }
}