【问题标题】:java, xsd & marshalling: jre bug, my fault or xsd issues?java、xsd 和编组:jre 错误、我的错还是 xsd 问题?
【发布时间】:2014-02-18 15:56:15
【问题描述】:

我在将 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 更新 45)

【问题讨论】:

  • 如果您可以发布一个实际产生该结果的小样本会更有帮助 - 仅在堆栈跟踪上很难诊断原因。您是否已经尝试过不同的 JVM 版本——即使在同一个主版本中?
  • @RomanVottner 你是对的,但不幸的是,我不允许发布这些 XSD 和相应的代码。但也许我可以尝试制作一个不使用实际文件的简约示例。
  • 除非您提供样本,否则没有人可以帮助您。
  • 您的架构是使用继承还是在element 中声明complexType? JAXB 可能在这两个方面都有问题,但您可以使用绑定自定义来解决它。 JAXB 似乎对替换组装傻了。
  • @LeosLiterak - 我能够根据他的异常重新创建示例代码:stackoverflow.com/a/23093089/383861

标签: java xml jaxb xsd


【解决方案1】:

TL;DR

java、xsd 和编组:jre 错误、我的错还是 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 类对应于一个匿名复杂类型。匿名类型用@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

演示代码 - 有效

演示

如果您指定了另一个子类 B 而不是 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 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>

【讨论】:

    猜你喜欢
    • 2012-01-24
    • 2015-08-13
    • 2012-09-03
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 2014-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多