JAXB-Eclipselink:XmlRootElement和继承

时间:2012-01-13 16:29:53

标签: inheritance jaxb eclipselink moxy

使用Eclipselink / MOXy 2.3我在编组XML时有以下用例:

abstract class MyAbstract {
}

class MyImpl extends MyAbstract {
}

class A {

    private MyAbstract myAbstract;

    // MyImpl is behind this
    public MyAbstract getMyAbstract() {
        return myAbstract;
    }

}

我在oxm.xml中定义了以下映射:

<java-type name="foo.MyAbstract" xml-accessor-type="NONE">
    <xml-see-also>
        foo.MyImpl
    </xml-see-also>
</java-type>

<java-type name="foo.MyImpl">
    <xml-root-element name="MyImpl" />
</java-type>

<java-type name="bar.A" xml-accessor-type="NONE">
    <xml-root-element name="A" />
    <java-attributes>
        <xml-element java-attribute="myAbstract" type="foo.MyAbstract" />
    </java-attributes>
</java-type>

现在导致:

<A>
    <myAbstract xsi:type="myImpl">
        <!-- Mapped members of MyImpl + MyAbstract -->
    </myAbstract>
</A>

由于我不想要导出的xml中的属性名称,我改变了:

<java-type name="bar.A" xml-accessor-type="NONE">
    <xml-root-element name="A" />
    <java-attributes>
        <xml-element java-attribute="myAbstract" type="foo.MyAbstract" xml-path="."/>
    </java-attributes>
</java-type>

导致:

<A>
    <!-- Members of MyImpl + MyAbstract marshalled without any wrapping element-->
</A>

我想要的是:

 <A>
    <MyImpl>
        <!-- Members of MyImpl + MyAbstract -->
    </MyImpl>
 </A>

问题是:我如何实现这一目标? MOXy只是忽略MyImpl上的XmlRootElement ......

修改

尝试Blaise建议给我以下例外:

Exception [EclipseLink-60] (Eclipse Persistence Services - 2.3.2.v20111125-r10461):   
org.eclipse.persistence.exceptions.DescriptorException
The method [] or [getMyAbstract] is not defined in the object [bar.A].

现在这需要我之前遗漏的更多信息,因为我认为它不相关:

A类是定义:public X getMyAbstract();的接口 MyAbstract实现了X(这就是为什么我在接口A的映射中添加了type-attribute的原因。)

因此,使用xml-element-ref MOXy不再“看到”getter,而是使用xml-element

1 个答案:

答案 0 :(得分:2)

您要查找的映射是@XmlElementRef。这与XML模式中的替换组的概念相对应。

<强>酒吧/ oxm.xml

以下是bar包的外部映射文档。注意myAbstract属性如何与xml-element-ref映射,@XmlElementRef<?xml version="1.0" encoding="UTF-8"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="bar"> <java-types> <java-type name="A" xml-accessor-type="NONE"> <xml-root-element name="A" /> <java-attributes> <xml-element-ref java-attribute="myAbstract"/> </java-attributes> </java-type> </java-types> </xml-bindings>

的XML表示形式
foo

<强>富/ oxm.xml

以下是<?xml version="1.0" encoding="UTF-8"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="foo"> <java-types> <java-type name="MyAbstract" xml-accessor-type="NONE"> <xml-see-also> foo.MyImpl </xml-see-also> </java-type> <java-type name="MyImpl"> <xml-root-element name="MyImpl" /> </java-type> </java-types> </xml-bindings> 包的外部元数据文件:

package forum8853855;

import java.util.*;
import javax.xml.bind.*;    
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import bar.A;
import foo.MyImpl;

public class Demo {

    public static void main(String[] args) throws Exception {
        List<String> oxm = new ArrayList<String>(2);
        oxm.add("foo/oxm.xml");
        oxm.add("bar/oxm.xml");

        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, oxm);

        JAXBContext jc = JAXBContext.newInstance(new Class[] {A.class}, properties);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        A a = new A();
        a.setMyAbstract(new MyImpl());
        marshaller.marshal(a, System.out);
    }

}

<强>演示

以下是此示例的演示代码:

<?xml version="1.0" encoding="UTF-8"?>
<A>
   <MyImpl/>
</A>

<强>输出

{{1}}

了解更多信息