使用 JAXB 从两个 XML 文件交叉引用 XmlID [英] Using JAXB to cross reference XmlIDs from two XML files

查看:27
本文介绍了使用 JAXB 从两个 XML 文件交叉引用 XmlID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将两个不同的 XML 文件编组/解组到 POJOS.第一个 XML 文件如下所示:

I'm trying to marshal/unmarshal from two different XML files to POJOS. The first XML file looks like this:

--Network.xml--
<Network>
  <Nodes>
    <Node id="ROD" />
    <Node id="KFI" />
    <Node id="JND" />
  </Nodes>
  <Arcs>
    <Arc fromNode="ROD" />
    <Arc fromNode="JND" />
  </Arcs>
</Network>
---------

使用@XmlID 和@XmlIDREF 注释,我可以成功填充 Arc 类以指向它引用的正确节点.

Using @XmlID and @XmlIDREF annotations, I can successfully populate the Arc classes to point to the correct Node which it references.

但是,我也必须解析这个 XML:

However, I also have to parse this XML:

--NetworkInputs.xml--
<NetworkInputs>
  <Flows>
    <Flow toNode="JND" />
    <Flow toNode="ROD" />
  </Flows>
</NetworkInputs>
------

目前,我的程序成功地解组了 Network 对象,但是 Network 和 NetworkInputs 之间没有连接,允许 JAXB查看"Network 中存在的节点.我希望我的 Flow 对象指向 Network 类中的正确节点.

Currently, my program unmarshals the Network object successfully, but there's no connection between Network and NetworkInputs that allows JAXB to "see" the nodes that exist in Network. I want my Flow objects to point to the correct Node in the Network class.

我基本上想这样做:http://old.nabble.com/JAXB-Unmarshalling-and-XmlIDREF-using-different-stores-td14035248.html

我尝试实现这个:http://weblogs.java.net/blog/kohsuke/archive/2005/08/pluggable_ididr.html它只是不起作用,因为我无法从静态上下文中获取已填充网络的节点数据.

I tried implementing this: http://weblogs.java.net/blog/kohsuke/archive/2005/08/pluggable_ididr.html and it just doesn't work, because I can't get the Node data for my populated Network from a static context.

有没有可能做这样的事情?

Is it even possible to do something like this?

推荐答案

这可以通过 XmlAdapter 来完成.诀窍是 XmlAdapter 需要使用 Network.xml 中的所有节点进行初始化,然后传递给与 NetworkInputs.xml 一起使用的 Unmarshaller:

This can be done with an XmlAdapter. The trick is the XmlAdapter will need to be initialized with all of the Nodes from Network.xml and passed to the Unmarshaller used with NetworkInputs.xml:

import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Network.class, NetworkInputs.class);

        File networkXML = new File("Network.xml");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Network network = (Network) unmarshaller.unmarshal(networkXML);

        File networkInputsXML = new File("NetworkInputs.xml");
        Unmarshaller unmarshaller2 = jc.createUnmarshaller();
        NodeAdapter nodeAdapter = new NodeAdapter();
        for(Node node : network.getNodes()) {
            nodeAdapter.getNodes().put(node.getId(), node);
        }
        unmarshaller2.setAdapter(nodeAdapter);
        NetworkInputs networkInputs = (NetworkInputs) unmarshaller2.unmarshal(networkInputsXML);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(networkInputs, System.out);
    }
}

诀窍是使用 XmlAdapter 映射 Flow 上的 toNode 属性:

The trick is to map the toNode property on Flow with an XmlAdapter:

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

public class Flow {

    private Node toNode;

    @XmlAttribute
    @XmlJavaTypeAdapter(NodeAdapter.class)
    public Node getToNode() {
        return toNode;
    }

    public void setToNode(Node toNode) {
        this.toNode = toNode;
    }

}

适配器将如下所示.诀窍是我们将一个配置的 XmlAdapter 传递给解组器:

The adapter will look like the following. The trick is that we will pass a configured XmlAdapter that knows about all the Nodes to the unmarshaller:

import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class NodeAdapter extends XmlAdapter<String, Node>{

    private Map<String, Node> nodes = new HashMap<String, Node>();

    public Map<String, Node> getNodes() {
        return nodes;
    }

    @Override
    public Node unmarshal(String v) throws Exception {
        return nodes.get(v);
    }

    @Override
    public String marshal(Node v) throws Exception {
        return v.getId();
    }

}

这篇关于使用 JAXB 从两个 XML 文件交叉引用 XmlID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆