【问题标题】:JAXB Marshalling and PolymorphismJAXB 编组和多态性
【发布时间】:2011-02-03 18:17:54
【问题描述】:

我有一个由 JAXB 生成的类的层次结构。我想将子类编组为基类元素(但具有所有子类属性),使用 xsi:type 来指示具体类型。

例如,给定一个 Animal 和一个 Bird 子类:

<xs:complexType name="animal" abstract="true">
    <xs:sequence>
        <xs:element name="name" type="xs:string"/>
    </xs:sequence>
</xs:complexType>

<xs:complexType name="bird">
    <xs:complexContent>
        <xs:extension base="animal">
            <xs:sequence>
                <xs:element name="maxAltitude" type="xs:int"/>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

<xs:element name="Animal" type="animal"/>
<xs:element name="Bird" type="bird"/>

无论我如何编组一只鸟,例如:

Bird sparrow = new Bird();
sparrow.setName("Sparrow");
sparrow.setMaxAltitude(1000);

JAXBContext context = JAXBContext.newInstance(Animal.class, Bird.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(sparrow, System.out);

结果总是一个 Bird 元素:

<Bird xmlns="http://mycompany.com/animals">
    <name>Sparrow</name>
    <maxAltitude>1000</maxAltitude>
</Bird>

然而我想要的是这个(子类的所有属性,xsi类型,基类元素名称):

<Animal xmlns="http://mycompany.com/animals"
        xsi:type="bird"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <name>Sparrow</name>
    <maxAltitude>1000</maxAltitude>
</Animal>

奇怪的是,如果我创建一个包装元素:

<xs:complexType name="animalWrapper">
    <xs:sequence>
        <xs:element name="Animal" type="animal"/>
    </xs:sequence>
</xs:complexType>

<xs:element name="AnimalWrapper" type="animalWrapper"/>

并编组它,它使用基类类型:

<AnimalWrapper xmlns="http://mycompany.com/animals"
    <Animal xsi:type="bird"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <name>Sparrow</name>
        <maxAltitude>1000</maxAltitude>
    </Animal>
</AnimalWrapper>

如果我手动构建所需的 XML 文档,JAXB 可以毫无问题地解组它。如何创作我的 XML 模式和/或配置 JAXB 以允许我想要的编组行为?

谢谢。

【问题讨论】:

    标签: java xsd jaxb polymorphism


    【解决方案1】:

    您可以执行以下操作:

    QName qName = jc.createJAXBIntrospector().getElementName(new Animal());
    JAXBElement<Animal> jaxbElement = new JAXBElement<Animal>(qName, Animal.class, new Bird());
    marshaller.marshal(jaxbElement, System.out);
    

    退房:

    【讨论】:

    • 谢谢。您的示例在多态项周围有一个包装器,例如我的 AnimalWrapper 示例,这不是我想要的。我想要根元素的多态性。
    • 谢谢。动物是抽象的,所以我不能完全做到这一点。我可以放宽我想的架构,但我不想这样做。我会尝试与您的建议类似的事情。
    • 您始终可以自己创建 QName,而不是使用自省器来获取它。
    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 2011-11-24
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 2014-05-04
    • 1970-01-01
    相关资源
    最近更新 更多