java,xsd&编组:jre bug,我的错还是xsd问题?

时间:2014-01-27 17:11:53

标签: java xml jaxb xsd

将JAXB模型树编组到xml文件时,我遇到了问题。

我使用 xjc 创建了这些模型类。 我无法修改这些xml架构 - 它们是在外部定义的(类似于缺少答案的this问题)。

根据xjc(以及其他xml工具),xml架构文件似乎是有效的。 我在问是否

  • 这是一个java / jre错误
  • 我做错了
  • 如果架构文件有些错误

以及如何解决此问题。

我得到的例外是:

com.sun.istack.internal.SAXException2: "com.mypackage.A" is substituting "com.mypackage.BaseType", but "com.mypackage.A" is bound to an anonymous type.
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:237)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:652)
    at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:685)
    at com.sun.xml.internal.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:54)
    at com.sun.xml.internal.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:157)
    at com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:144)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:335)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:685)
    at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:335)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:685)
    at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:685)
    at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:685)
    at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143)
    at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:146)
    at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:116)
    at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:318)
    at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:325)
    at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:61)
    at com.sun.xml.internal.bind.v2.runtime.property.ArrayReferenceNodeProperty.serializeListBody(ArrayReferenceNodeProperty.java:103)
    at com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:144)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:685)
    at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:685)
    at com.sun.xml.internal.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:54)
    at com.sun.xml.internal.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:157)
    at com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:144)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:685)
    at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:141)
    at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:116)
    at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:318)
    at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:325)
    at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:61)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:483)
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308)
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236)
    at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:95)

(java 7 update 45)

1 个答案:

答案 0 :(得分:10)

TL; DR

  

java,xsd&编组:jre bug,我的错还是xsd问题?

这是你的错:)。继续阅读原因。


Java模型

以下是基于您的问题中暗示的Java模型,该模型可用于产生您所看到的相同异常。

<强>根

以下是具有一个属性的根对象。该属性的类型有两个子类。其中一个子类(B)对应于一个命名类型,另一个(A)对应于匿名类型。

package com.mypackage;

import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Root {

    private BaseType baseType;

    public BaseType getBaseType() {
        return baseType;
    }

    public void setBaseType(BaseType baseType) {
        this.baseType = baseType;
    }

}

<强>碱基类型

这是超级课程。它有两个子类:AB

package com.mypackage;

import javax.xml.bind.annotation.XmlSeeAlso;

@XmlSeeAlso({A.class, B.class})
public class BaseType {

}

<强> A

A类对应于匿名复杂类型。匿名类型使用@XmlType(name="")注释表示。

package com.mypackage;

import javax.xml.bind.annotation.XmlType;

@XmlType(name="")
public class A extends BaseType {

}

<强>乙

B类对应于命名的复杂类型b。默认值与@XmlType(name="b")相同。

package com.mypackage;

public class B extends BaseType {

}

演示代码 - 重现错误

<强>演示

baseType类的Root属性是其中一个子类时,添加xsi:type属性以限定元素(类似于Java中的强制转换)。该实例需要对应于命名的复杂类型。在这种情况下,A不会。

package com.mypackage;

import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Root root = new Root();
        BaseType baseType = new A(); // Invalid Value
        root.setBaseType(baseType);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

<强>异常

这会导致以下异常。正如异常A所述,它不是BaseType的有效替代,因为它对应于匿名复杂类型,因为它对应于匿名类型,它没有{{1}的必要值。 1}}属性。

xsi:type

演示代码 - 有效

<强>演示

如果不是Exception in thread "main" javax.xml.bind.MarshalException - with linked exception: [com.sun.istack.internal.SAXException2: Instance of "com.mypackage.A" is substituting "com.mypackage.BaseType", but "com.mypackage.A" is bound to an anonymous type.] at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:311) at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236) at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:95) at com.mypackage.Demo.main(Demo.java:16) Caused by: com.sun.istack.internal.SAXException2: Instance of "com.mypackage.A" is substituting "com.mypackage.BaseType", but "com.mypackage.A" is bound to an anonymous type. at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:237) at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:652) at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143) at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343) at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:582) at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:325) at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:483) at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308) ... 3 more 而是指定了与命名复杂类型对应的另一个子类A

B

<强>输出

然后,您将看到所有内容都按预期工作,并且在编组package com.mypackage; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); Root root = new Root(); BaseType baseType = new B(); // Valid Value root.setBaseType(baseType); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } } 属性时包含类型名称。

baseType