使用 JAXB 处理设计不佳的 XML
- 作者: 不狂妄怎是男人作风_
- 来源: 51数据库
- 2022-11-30
问题描述
我目前正在使用 JAXB 替换旧系统,但在解析 XML 时遇到了问题.系统的第一个要求是它必须是插入式替换,因此我无法修改 XML 的格式.下面是给我带来麻烦的 XML 部分.
I'm currently working on replacing a legacy system with JAXB and I'm running into problem with parsing the XML. The number one requirement of the system is that it must be a drop-in replacement so I cannot modify the format of the XML. Below is the XML section that is giving me trouble.
<xx> <s1> <X>-9999</X> <Y>-9999</Y> </s1> <s2> <X>-9999</X> <Y>-9999</Y> </s2> </xx>
XML 的问题是所有 s# 对象都完全相同,最多可以有 256 个.JAXB 中有没有办法注释这样的标签,还是我必须创建 256 个单独的注释?任何帮助将不胜感激.
The issue with the XML is that all of the s# objects are the exact same and there can be up to 256 of them. Is there a way in JAXB to annotate such a tag or do I have to create 256 separate annotations? Any help would be most appreciated.
这里是 xx 对象的 java 代码.注意:该对象最初是在理解只有 2 个 s# 对象的情况下进行编程的,但此后发生了变化.
Here is the java code for the xx object. Note: the object was originally programmed with the understanding that there would only be 2 s# objects, but that since has changed.
@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 对象:
And here is the XMLSite object:
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# 处的项作为一个集合来处理:
If you want to handle at the s# items as a collection:
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<XMLSite> sites; @XmlElement(name="s") public List<XMLSite> getSites() { return sites; } public void setSites(List<XMLSite> sites) { this.sites = sites; } }
然后你可以做一些事情,比如欺骗 JAXB,让他们认为所有元素(s1、s2 等)实际上都称为 s:
Then you could do something like to fool JAXB into thinking all the elements (s1, s2, etc) are actually called 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; } } }
类似的例子见:
- http://bdoughan.blogspot.com/2010/12/case-insensitive-unmarshalling.html