如果没有@XmlRootElement,将Choice与Any组合就无法编组

时间:2013-12-06 18:05:35

标签: jaxb

我正在使用JAX-B从预定义的XSD生成POJO。 我遇到了这个元素定义

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="http://order.example.com"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://order.example.com"
    elementFormDefault="qualified"
    attributeFormDefault="unqualified">

    <xs:element name="Order">
        <xs:complexType>
            <xs:sequence>
                <xs:choice maxOccurs="unbounded">
                    <xs:choice minOccurs="0" maxOccurs="3">
                        <xs:element name="Credit" type="CreditType" form="qualified"/>
                        <xs:element name="GiftCard" type="GiftCardType" form="qualified"/>
                    </xs:choice>
                    <xs:any namespace="##other" processContents="lax"/>
                </xs:choice>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="CreditType">
        <xs:sequence>
            <xs:element name="Number" type="xs:string" />
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="GiftCardType">
        <xs:sequence>
            <xs:element name="Code" type="xs:long" />
        </xs:sequence>
    </xs:complexType>

</xs:schema>

正如您所注意到的那样,嵌套&lt; choice /&gt;的组合非常糟糕。与&lt; any /&gt;。

XJC生成此代码:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "creditOrGiftCardOrAny"
})
@XmlRootElement(name = "Order")
public class Order {

    @XmlElementRefs({
        @XmlElementRef(name = "GiftCard", namespace = "http://order.example.com", type = JAXBElement.class, required = false),
        @XmlElementRef(name = "Credit", namespace = "http://order.example.com", type = JAXBElement.class, required = false)
    })
    @XmlAnyElement(lax = true)
    protected List<Object> creditOrGiftCardOrAny;
}

该属性引用JAXBElements而不是生成的CreditType和GiftCardType类。

如果我尝试编组一个这样的Order对象:

Order order = new Order();
CreditType credit = new CreditType();
credit.setNumber("4111111111111111");
order.getCreditOrGiftCardOrAny().add(credit);

JAXBContext jaxbContext = JAXBContext.newInstance(Order.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.marshal(order, System.out);

我收到以下错误:

[com.sun.istack.internal.SAXException2: unable to marshal type "com.example.order.CreditType" as an element because it is missing an @XmlRootElement annotation]

可以通过添加一个强制XJC注释类的绑定来解决这个问题,问题是在我的情况下我发生了很多这个问题,因此必须为每种类型添加一个绑定并不能很好地扩展。

任何人都有更好的建议吗?

我上传了一个重现该问题的maven项目:https://github.com/jcfandino/jaxb-choice 跑吧:

git clone https://github.com/jcfandino/jaxb-choice.git && cd jaxb-choice
mvn test

0 个答案:

没有答案