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

查看:127
本文介绍了使用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和NetworkInput之间没有任何连接,允许JAXB看到网络中存在的节点。我希望我的Flow对象指向Network类中的正确Node。

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-使用-different-stores-td14035248.html

I basically want to do this: 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来完成。诀窍是需要使用Network.xml中的所有节点初始化XmlAdapter,并将其传递给与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);
    }
}

诀窍是在Flow上映射toNode属性一个XmlAdapter:

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传递给unmarshaller:

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天全站免登陆