【问题标题】:Dealing with poorly designed XML with JAXB使用 JAXB 处理设计不佳的 XML
【发布时间】:2011-07-07 19:54:53
【问题描述】:

我目前正在使用 JAXB 替换旧系统,但在解析 XML 时遇到了问题。系统的第一个要求是它必须是插入式替换,因此我无法修改 XML 的格式。下面是给我带来麻烦的 XML 部分。

<xx>
    <s1>
        <X>-9999</X>
        <Y>-9999</Y>
    </s1>
    <s2>
        <X>-9999</X>
        <Y>-9999</Y>
   </s2>
</xx>

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

【问题讨论】:

  • 256 个什么?请具体。
  • 标签。所以可能有 等,每个标签都有 标签作为子标签
  • 您的目标对象模型是什么样的?我领导一个 JAXB 实现,可能知道一些可以提供帮助的技巧。
  • 我不完全确定您对 Blaise 的要求(我对使用 JAXB 非常陌生,并且是一名初级开发人员)。你想看看我试图将 XML 解析成的 Java 对象吗?
  • 是的,这正是我想要的。

标签: java jaxb


【解决方案1】:

如果您想将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<XMLSite> sites;

    @XmlElement(name="s")
    public List<XMLSite> getSites() {
        return sites;
    }

    public void setSites(List<XMLSite> 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;
        }

    }
}

类似的例子见:

【讨论】:

  • 非常感谢,这正是我所需要的。
【解决方案2】:

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

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

【讨论】:

  • 感谢您提供的信息,我将不得不考虑手动解析它。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2016-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-02
      • 2011-10-07
      • 2011-05-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多