gpt4 book ai didi

java - 最新 JAXB 版本 (Java 7) 中的 XmlID/XmlIDREF 和继承

转载 作者:搜寻专家 更新时间:2023-10-31 20:30:21 26 4
gpt4 key购买 nike

我正在使用@XmlID 和@XmlIDREF 标记从一个对象引用另一个对象。即使使用继承类,它在 Java 6 中也能正常工作。我创建的示例代码如下所示。基类使用的标签:

@XmlRootElement
@XmlAccessorType(FIELD)
public class Module {
Module() {}

@XmlIDREF
private Module other;

@XmlID
private String id;

public Module(String id, Module other) {
this.id = id;
this.other = other;
}
}

继承类:

@XmlRootElement
public class TheModule extends Module {
TheModule() {}

private String feature;

public TheModule(String id, Module other, String feature) {
super(id, other);
this.feature = feature;
}
}

这些类的容器:

@XmlRootElement
public class Script {
Script() {}
public Script(Collection<Module> modules) {
this.modules = modules;
}

@XmlElementWrapper
@XmlElementRef
Collection<Module> modules = new ArrayList<Module>();
}

运行此示例代码时:

public class JaxbTest {

private Script createScript() {
Module m1 = new Module("Module1", null);
Module m2 = new TheModule("Module2", m1, "featured module");
Module m3 = new Module("Module3", m2);
return new Script(Arrays.asList(m1, m2, m3));
}

private String marshal(Script script) throws Exception {
JAXBContext context = JAXBContext.newInstance(Module.class, Script.class, TheModule.class);
Writer writer = new StringWriter();
context.createMarshaller().marshal(script, writer);
return writer.toString();
}

private void runTest() throws Exception {
Script script = createScript();

System.out.println(marshal(script));
}

public static void main(String[] args) throws Exception {
new JaxbTest().runTest();
}
}

我在 Java 6 中接收 XML:

<script>
<modules>
<module>
<id>Module1</id>
</module>
<theModule>
<other>Module1</other>
<id>Module2</id>
<feature>featured module</feature>
</theModule>
<module>
<other>Module2</other>
<id>Module3</id>
</module>
</modules>
</script>

请注意,对 m2(TheModule 实例)的引用已按预期序列化。但是当相同的代码在 Java 7 (Jaxb 2.2.4-1) 下运行时,我收到:

<script>
<modules>
<module>
<id>Module1</id>
</module>
<theModule>
<other>Module1</other>
<id>Module2</id>
<feature>featured module</feature>
</theModule>
<module>
<other xsi:type="theModule" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<other>Module1</other>
<id>Module2</id>
<feature>featured module</feature>
</other>
<id>Module3</id>
</module>
</modules>
</script>

因此您可以看到在最新的 JAXB 上,继承模块的 @XmlIDREF 不起作用!

最佳答案

这个答案是错误的。不要依赖它,而是阅读 JAXBContext.newInstance(...) 的文档, 请参阅 this answer以及下面的评论。


我认为您将 JAXB 与以下行混淆了。

JAXBContext.newInstance(Module.class, Script.class, TheModule.class);

您告诉它您想要序列化 ​​XML 类型 ScriptModuleTheModule。 JAXB 将以特殊 方式处理后一种类型的对象,因为您已经提供了它的基类:它向它添加了一个区分属性。这样可以在序列化的 XML 中区分这两种类型。

尝试只提供 ScriptModule所有 模块的基类。

JAXBContext.newInstance(Module.class, Script.class);

事实上,您可以完全省略 Module。 JAXB 将推断您尝试从上下文序列化的 Script 对象中的类型。

顺便说一下,这种行为与 Java 6 并不完全相关。它与正在使用的 JAXB 实现相关(好吧,好吧,几乎是同一回事,我知道)。在我的项目中,我使用 JAXB 2.2.4-1,它也在 Java 6 和 7 中重现了手头的问题。

哦,还有一件事:不是创建 StringWriter 并将对象编码到其中,然后将其内容发送到 System.out,您可以使用以下内容发送格式化的 XML 到 stdout

Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(script, System.out);

也许这可以简化(一点点)进一步的测试。

关于java - 最新 JAXB 版本 (Java 7) 中的 XmlID/XmlIDREF 和继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8228022/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com