我正在尝试创建一个对象模型,以便能够使用JAXB输出以下XML:
<root version="1">
<first version="1"/>
</root>
或者这个:
<root version="1">
<second version="1"/>
</root>
显然是这个例子的过度简化版本。只能存在first
或second
类型的子元素,而不能同时存在。
我的根元素如下所示:
@XmlRootElement(name = "root")
public class ExampleRootElement {
private int version;
private ExampleBaseSubElement subElement;
@XmlAttribute(name = "version")
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public ExampleBaseSubElement getSubElement() {
return subElement;
}
public void setSubElement(ExampleBaseSubElement subElement) {
this.subElement = subElement;
}
}
由于子元素必须是first
或second
,我创建了一个空的抽象虚拟类ExampleBaseSubElement
,以便从first
和{{的特定类中扩展1}}。我会在这里使用一个接口,但显然JAXB无法处理这些。 (我通常在C#中使用这种东西,所以请原谅,如果这是使用JAXB在Java中执行它的一种非常糟糕的方法)
虚拟课程:
second
public abstract class ExampleBaseSubElement {
}
的代码:
first
@XmlRootElement(name="first")
public class ExampleFirstSubElement extends ExampleBaseSubElement {
private int version;
@XmlAttribute(name="version")
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
}
的代码:(仅为了这个示例与second
几乎相同)
first
我可能错误的是期望使用@XmlRootElement(name = "second")
public class ExampleSecondSubElement extends ExampleBaseSubElement {
private int version;
@XmlAttribute(name = "version")
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
}
注释从类中设置元素名称,因为它不起作用。我试图通过使用嵌套XmlRootElement
创建ExampleRootElement
来创建所需的XML输出:
ExampleFirstSubElement
这导致:
ExampleRootElement exampleRootElement = new ExampleRootElement();
exampleRootElement.setVersion(1);
ExampleFirstSubElement exampleFirstSubElement = new ExampleFirstSubElement();
exampleFirstSubElement.setVersion(1);
exampleRootElement.setSubElement(exampleFirstSubElement);
JAXBContext jaxbContext = JAXBContext.newInstance(ExampleRootElement.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(exampleRootElement, System.out);
期望是:
<root version="1">
<subElement/>
</root>
好的,我知道这不起作用。简单地忽略了注释。可能是因为JAXB没有解析扩展类型,这可以解释为什么嵌套元素的属性<root version="1">
<first version="1"/>
</root>
也会丢失。而且我非常乐观地认为,解组这个问题会更加困难......
所以我的问题是:我在这里错过了某种神奇的注释,所以这可以按预期工作,或者这完全是错误的方法,如果是这样,最佳做法是什么?
答案 0 :(得分:0)
好的,在修补了不同的注释(基本上是强制性的)后,我提出了以下解决方案:
将XmlSeeAlso
添加到抽象基类ExampleBaseSubElement
:
@XmlSeeAlso({
ExampleFirstSubElement.class,
ExampleSecondSubElement.class
})
public abstract class ExampleBaseSubElement {
}
在XmlElementRef
内向subElement
的getter添加ExampleRootElement
:
@XmlRootElement(name = "root")
public class ExampleRootElement {
private int version;
private ExampleBaseSubElement subElement;
@XmlAttribute(name = "version")
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
@XmlElementRef // here!
public ExampleBaseSubElement getSubElement() {
return subElement;
}
public void setSubElement(ExampleBaseSubElement subElement) {
this.subElement = subElement;
}
}
现在产生预期的输出:
<root version="1">
<first version="1"/>
</root>
我仍然不确定这一般是坏还是实际上应该怎么做。它有效,我希望这有助于其他人面临同样的问题。