Java、XSD & Marshalling:JRE Bug、My fault or XSD 问题?



我正在遇到问题,而编组 jaxb模型树到XML文件。

我使用 XJC 创建了这些模型类。我无法修改这些XML模式 - 它们是外部定义的(类似于缺乏答案的问题)。

根据XJC(和其他XML工具),XML架构文件似乎是有效的。我问

是否
  • 这是Java/jre bug
  • 我做错了
  • 如果模式文件有些错误

以及如何解决此问题。

我得到的例外是:

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)

tl; dr

Java,XSD&编组:JRE错误,我的错或XSD问题?

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


Java模型

以下是一种Java模型,基于您的问题中暗示的一个模型,可用于产生与您看到的相同例外。

root

下面是一个具有一个属性的根对象。该属性的类型有两个子类。其中一个子类(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;
    }
}

astetype

这是超级阶级。它有两个子类: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类对应于指定的复杂类型b。默认值与具有@XmlType(name="b")

相同
package com.mypackage;
public class B extends BaseType {
}

演示代码 - 重现错误

演示

Root类上的baseType属性是子类之一时,则添加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的有效替代品,因为它对应于匿名复杂类型,因为它与匿名类型相对应,因此它没有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属性编辑时,包含类型名称。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <baseType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="b"/>
</root>

最新更新