Java 如何避免使用JAXB和具有类似结构的类似容器的元素进行代码复制
形势 我使用MOXy的JAXB实现来处理一个大型XML文档,该文档的模式有许多相似的复杂类型。具体来说,大约有24种类型充当具有以下结构的列表包装器元素:Java 如何避免使用JAXB和具有类似结构的类似容器的元素进行代码复制,java,xml,jaxb,Java,Xml,Jaxb,形势 我使用MOXy的JAXB实现来处理一个大型XML文档,该文档的模式有许多相似的复杂类型。具体来说,大约有24种类型充当具有以下结构的列表包装器元素: <ITEMS attr1="X" attr2="Y"> <ITEM>...</ITEM> ... <EXTENSION/> <ITEMS> ... ... 对于这些类似于列表包装器的元素中的每一个,名称都会更改,所包含的列表元
<ITEMS attr1="X" attr2="Y">
<ITEM>...</ITEM>
...
<EXTENSION/>
<ITEMS>
...
...
对于这些类似于列表包装器的元素中的每一个,名称都会更改,所包含的列表元素也会更改。但是,属性(都是可选的)和单个扩展元素(也是可选的)始终存在。以下是两种类型的使用示例:
<ROLES visible="false">
<ROLE type="X"/>
<ROLE type="Y"/>
</ROLES>
<PAYMENTS visible="true">
<PAYMENT>
<PAYEENAME>Joe</PAYEENAME>
</PAYMENT>
<EXTENSION>
<SOMETHING>Here</SOMETHING>
</EXTENSION>
</PAYMENTS>
乔
在这里
问题
我希望避免代码重复,因为这些元素之间唯一的变化是名称及其包含的一个或多个元素。最好的方法是什么
我只能看到两种可能的解决办法
1
使用泛型创建具体类,以指示要在发生更改的集合中使用的对象类型。然后使用MOXy的外部OX映射来指示该类的任何单独使用应该如何序列化。比如:
公共类GenericContainer{
@XmlAttribute
保护布尔可视性;
@xmlement(name=“扩展”)
受保护的扩展;
//在外部元文件中完成的OX映射
受保护的清单项目;
...
}
虽然我喜欢这个选项,但似乎不可能在每次使用的基础上重新定义类的OX映射
2
创建不带List属性的基类,然后为每个自定义包装器元素创建一个具体类。这个解决方案确实有效,但我最终会得到大约24个近似相同的类
要么是1可能,要么是有更好的方法来处理这个问题,我还没有想到
提前谢谢 公共类GenericContainer{
public class GenericContainer {
private Boolean visible;
private Object extension;
private List<Object> nodes;
@XmlAttribute
public Boolean isVisible() {
return visible;
}
public void setVisible(Boolean visible) {
this.visible = visible;
}
@XmlElement(name="EXTENSION")
public Object getExtension() {
return extension;
}
public void setExtension(Object extension) {
this.extension = extension;
}
@XmlAnyElement
public List<Object> getNodes() {
return nodes;
}
public void setNodes(List<Object> nodes) {
this.nodes = nodes;
}
}
私有布尔可见;
私有对象扩展;
私有列表节点;
@XmlAttribute
公共布尔值可见(){
返回可见;
}
公共void集合可见(布尔可见){
可见的;可见的;
}
@xmlement(name=“扩展”)
公共对象getExtension(){
返回扩展;
}
公共void集合扩展(对象扩展){
这个扩展=扩展;
}
@XmlAnyElement
公共列表getNodes(){
返回节点;
}
公共void集合节点(列表节点){
this.nodes=节点;
}
}
和读取XML实例
JAXBContext jaxbContext = JAXBContext.newInstance("jaxbtest1");
Unmarshaller um = jaxbContext.createUnmarshaller();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new File("src/test1.xml"));
Node node = doc.getFirstChild();
JAXBElement<GenericContainer> jaxbE = um.unmarshal(node, GenericContainer.class);
GenericContainer gc = jaxbE.getValue();
Boolean vis = gc.isVisible();
Element ext = (Element)gc.getExtension();
for(Object o : gc.getNodes()) {
Element listItem = (Element)o;
}
JAXBContext JAXBContext=JAXBContext.newInstance(“jaxbtest1”);
Unmarshaller um=jaxbContext.createUnmarshaller();
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
DocumentBuilder db=dbf.newDocumentBuilder();
documentdoc=db.parse(新文件(“src/test1.xml”);
Node=doc.getFirstChild();
JAXBElement jaxbE=um.unmarshal(节点,GenericContainer.class);
GenericContainer gc=jaxbE.getValue();
布尔vis=gc.isVisible();
元素ext=(元素)gc.getExtension();
对于(对象o:gc.getNodes()){
元素列表项=(元素)o;
}
但是代码复制真的很重要吗?如果您的模式具有列表容器类型的公共扩展基础,并且您正在使用xjc,那么为什么要避免使用不同的类呢?毕竟,JAXB背后的思想是为每个独特的复杂类型都有一个值类
如果您能够设计出处理类似但不同的XML类型的通用逻辑,并且不需要大量Java类,那么您可以切换到StAX。这个示例并不真正符合我的要求,除非我遗漏了什么。它实际上不允许我将列表元素绑定到JAXB注释类,因为解组器会将所有内容都转换为org.w3c.dom.Element对象。换一种方式会少一点麻烦,但没有类型安全性。对于你关于代码复制的问题,你是对的,这并不十分重要。我真的很讨厌这样做。我最终选择了30多个几乎相同的课程,尽管我对此并不欣喜若狂。理想的情况是创建我自己的自定义java.util.Collection类,并提供泛型支持,但目前看来这是不可能的。