JAXB 生成不需要的 @XMLValue

JAXB generating unwanted @XMLValue

现在已经解决了大约半个星期的问题,需要帮助,因为我似乎无法取得任何进展。

我继承了一个 8 年没有得到很好对待的应用程序....仍然在 Java 1.4,Maven1 构建,8 年没有新的单元测试...

目前升级到 Java 1.6(Java 1.8 分支也同时完成,将测试两者)和 Maven 3.3.3 正在顺利进行 - 取得了很好的进展。

现在碰壁了,暂时没有突破

旧源使用本地 JAXB 1.3 jar 从大型 XSD.

生成 classes

我不得不从 JAXB1.3 迁移到 JAXB2.1 - 这也意味着随着命名约定的改变,我不得不花费大量时间重写对生成的 classes 的所有引用。 总之,编译代码花了很多时间。

最后,它编译了,我尝试了一个单元测试,看看它是如何工作的。 这是我遇到问题的地方。

大多数 classes 编译工作正常,但当我尝试生成 JAXBContext 时,其中三个包抛出异常:

派生另一个 class.

的 class 不允许

@XmlValue

我已将问题缩小为出现在几个生成的 classes 中的模式。 导致异常的class在schema中定义如下:

    <xs:element name="ContactName">
    <xs:complexType>
        <xs:simpleContent>
            <xs:extension base="xs:string">
                <xs:attribute name="First" type="xs:string"/>
                <xs:attribute name="Middle" type="xs:string"/>
                <xs:attribute name="Last" type="xs:string"/>
                <xs:attribute name="Name" type="xs:string"/>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>
</xs:element>

然后这个元素在另一个中引用如下:

<xs:element name="ContactInfo">
    <xs:complexType>
        <xs:annotation>
            <xs:documentation>Common contact information</xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element ref="ContactName" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element ref="ContactID" minOccurs="0"/>
            <xs:element ref="ContactDivision" minOccurs="0" maxOccurs="unbounded"/>
            .....

生成为:

联系人姓名:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "value"
})
@XmlRootElement(name = "ContactName")
public class ContactName
    extends BaseJaxbDoc
    implements Serializable, Cloneable, CopyTo
{

    private final static long serialVersionUID = 47110815L;
    @XmlValue
    protected String value;
    @XmlAttribute(name = "First")
    protected String first;
    @XmlAttribute(name = "Middle")
    protected String middle;
    @XmlAttribute(name = "Last")
    protected String last;
    @XmlAttribute(name = "Name")
    protected String name;

然后在ContactInfo中声明如下:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "contactName",
    "contactID",
    "contactDivision",
    "contactPhone",
    "contactPhoneHome",
    "contactPhoneMobile",
    "contactFax",
    "contactEmail",
    "contactEmail2"
})
@XmlRootElement(name = "ContactInfo")
public class ContactInfo
    extends BaseJaxbDoc
    implements Serializable, Cloneable, CopyTo
{

    private final static long serialVersionUID = 47110815L;
    @XmlElement(name = "ContactName")
    protected List<ContactName> contactName;

抛出的异常在:

this problem is related to the following location:
    at protected java.lang.String xxx.xx.xxxx.xxxx.orders.jaxb.ContactName.value
    at xxx.xx.xxxx.xxxx.orders.jaxb.ContactName
    at protected java.util.List xxx.xx.xxxx.xxxx.orders.jaxb.ContactInfo.contactName
    at xxx.xx.xxxx.xxxx.orders.jaxb.ContactInfo
    at protected java.util.List xxx.xx.xxxx.xxxx.orders.jaxb.CustomerReference.contactInfo
    at xxx.xx.xxxx.xxxx.orders.jaxb.CustomerReference
    at protected java.util.List xxx.xx.xxxx.xxxx.orders.jaxb.Item.customerReference
    at xxx.xx.xxxx.xxxx.orders.jaxb.Item
    at public xxx.xx.xxxx.xxxx.orders.jaxb.Item xxx.xx.xxxx.xxxx.orders.jaxb.ObjectFactory.createItem()
    at xxx.xx.xxxx.xxxx.orders.jaxb.ObjectFactory

对原始模式进行了 XML 转换,删除了注释并创建了 jaxb:typesafeEnum 类型。然后将转换后的模式与 jxb 绑定文件一起使用,将所有内容绑定到内部 jaxb 助手 superclass - BaseJaxbDoc

        <jaxb:globalBindings generateIsSetMethod="true">
        <xjc:serializable uid="47110815"/>
        <xjc:superClass name="xxx.xx.xxxx.xxxx.helpers.BaseJaxbDoc"/>
        <jaxb:javaType name="java.math.BigDecimal" xmlType="xs:decimal" 
             parseMethod="xxx.xx.xxxx.xxxx.helpers.AmountConverter.parseAmount" 
            printMethod="xxx.xx.xxxx.xxxx.helpers.AmountConverter.printAmount"/>
        </jaxb:globalBindings>

这是因为我在 9 个不同的模式上使用 xjc,所有模式都生成 classes 的 JAXB 包。

classes 都有相同的 superclass(在每个模式的绑定文件中定义)只实现 JAXB marshall/unmarshallclasses 一次,以及其他一些辅助功能。 所以我的问题是当我无法修改模式时如何解决这个异常? XSLT 中的内容或绑定文件中的内容?

我的 Maven 依赖项: 对于 JAXB: org.jvnet.jaxb2.maven2 maven-jaxb21-插件 0.13.0

JAXB 运行时: org.glassfish.jaxb jaxb 运行时 2.2.11

尝试用 @XmlTransient 注释 BaseJaxbDoc

你遇到的问题产生了here:

                if(getBaseClass()!=null) {
                    builder.reportError(new IllegalAnnotationException(
                        Messages.XMLVALUE_IN_DERIVED_TYPE.format(), p ));
                }

JAXB 认为您的 BaseJaxbDoc 是一个基础 class。因此,您应该删除 xjc:superClass 或让 JAXB 认为您的 class 没有基础 class.

当我在 ModelBuilder 中查看 this part of the code 时:

        if(reader.hasClassAnnotation(clazz,XmlTransient.class) || isReplaced) {
            // handle it as if the base class was specified
            r = getClassInfo( nav.getSuperClass(clazz), searchForSuperClass,
                    new ClassLocatable<C>(upstream,clazz,nav) );
        }

似乎 ModelBuilder 在 class 上识别了 @XmlTransient 而没有考虑它们。因此,在您的 BaseJaxbDoc 上分配 @XmlTransient 可能会有所帮助。

另一种选择是放弃 BaseJaxbDoc 结构。您使用 class 继承将 marshal/unmarshal 功能添加到模式派生的 classes。我宁愿将此功能移出到某些外部服务中。这可能不是一个选项,因为您可能面临很多遗留代码。

另一种选择是在运行时尝试使用 MOXy 而不是 JAXB RI。