如何使用具有类似结构的类似容器的元素使用JAXB来避免代码重复

时间:2012-07-12 03:24:36

标签: java xml jaxb

情况

我正在使用MOXy的JAXB实现来处理大型XML文档,其架构有许多类似的复杂类型。具体来说,大约有24种类型作为列表包装元素,具有以下结构:

<ITEMS attr1="X" attr2="Y">
  <ITEM>...</ITEM>
  ...
  <EXTENSION/>
<ITEMS>

对于这些类似于list-wrapper的元素中的每一个,名称都会更改,并且包含的​​列表元素会发生更改。但是,始终存在属性(都是可选的)和单个EXTENSION元素(也是可选的)。以下是两种类型的使用示例:

<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映射来指示如何对类的任何个人使用进行序列化。类似的东西:

public class GenericContainer<T> {
 @XmlAttribute
 protected Boolean visibile;
 @XmlElement(name = "Extension")
 protected Extension extension;

 // OX Mappings done in external meta file
 protected List<T> items;
 ...
}

虽然我喜欢这个选项,但似乎无法按用户重新定义类的OX映射。

2

创建没有List属性的基类,然后为每个自定义包装元素创建一个具体类。这个解决方案肯定有效,但我最终会得到大约二十几个近乎相同的类。

要么#1可行还是有更好的方法来解决这个我没想过的问题?

提前致谢!

1 个答案:

答案 0 :(得分:0)

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;
}

}

并阅读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;
    }

但代码重复真的很重要吗?如果您的架构具有列表容器类型的公共扩展基础,并且您正在使用xjc,为什么要避免使用不同的类?毕竟JAXB背后的想法是为每个唯一的复杂类型设置一个值类。

如果您可以创建处理类似但不同的XML类型且不需要大量Java类的通用逻辑,则可以切换到StAX。