使用JAXB处理设计不佳的XML

我目前正在使用JAXB替换遗留系统,我遇到了解析XML的问题。 系统的首要要求是它必须是替代品,因此我无法修改XML的格式。 下面是给我带来麻烦的XML部分。

  -9999 -9999   -9999 -9999   

XML的问题在于所有s#对象都完全相同,最多可以有256个。 在JAXB中有一种方法可以注释这样的标记,还是我必须创建256个单独的注释? 非常感激任何的帮助。

这是xx对象的java代码。 注意:该对象最初编程时理解只有2个s#对象,但自那以后已经改变了。

 @XmlRootElement(name="xx") public class XMLXx implements Serializable { private static final long serialVersionUID = 4064597372833234503L; private XMLSite siteOne; private XMLSite siteTwo; @XmlElement(name="s1") public XMLSite getSiteOne() { return siteOne; } public void setSiteOne(XMLSite s1) { this.siteOne = s1; } @XmlElement(name="s2") public XMLSite getSiteTwo() { return siteTwo; } public void setSiteTwo(XMLSite s2) { this.siteTwo = s2; } } 

这是XMLSite对象:

 public class XMLSite implements Serializable { private static final long serialVersionUID = -4374405403222014476L; private Integer x; private Integer y; @XmlElement(name="X") public Integer getX() { return x; } public void setX(Integer x) { this.x = x; } @XmlElement(name="Y") public Integer getY() { return y; } public void setY(Integer y) { this.y = y; } } 

如果要将s#项目作为集合处理:

 import java.io.Serializable; import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name="xx") public class XMLXx implements Serializable { private static final long serialVersionUID = 4064597372833234503L; private List sites; @XmlElement(name="s") public List getSites() { return sites; } public void setSites(List sites) { this.sites = sites; } } 

然后你可以做一些类似的事情来欺骗JAXB认为所有元素( s1s2等)实际上都被称为s

 import java.io.FileInputStream; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.util.StreamReaderDelegate; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(XMLXx.class); XMLInputFactory xif = XMLInputFactory.newInstance(); XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("input.xml")); xsr = new SiteStreamReaderDelegate(xsr); Unmarshaller unmarshaller = jc.createUnmarshaller(); XMLXx object = (XMLXx) unmarshaller.unmarshal(xsr); System.out.println(object.getSites().size()); } private static class SiteStreamReaderDelegate extends StreamReaderDelegate { public SiteStreamReaderDelegate(XMLStreamReader xsr) { super(xsr); } @Override public String getLocalName() { String localName = super.getLocalName(); if(localName.startsWith("s")) { return "s"; } return localName; } } } 

有关类似示例,请参阅:

JaxB不支持“动态”标签。 由于只能有256个,所以使用脚本生成源代码。

不,我不这么认为,不是标准的JAXB。 原则上你可以使用@XmlMixed ,但你仍然会得到一堆DOM Element对象,而不是绑定类。 但是,一些专有的JAXB扩展(如MOXy)可能能够处理它。

对于JAXB来说,这不是一个很好的用例。 如你所说,XML的设计很差。 您最好手动解析(使用例如STAX或DOM),并自己构建所需的对象模型。

在freemarker / velocity等中写一个meta-XSD。 它可以使用for循环将256种类型定义为某些父类型的子类型。 如果要完全自动化,可以编写maven插件,从freemarker生成XSD,并在结果上运行generate-sources。