Using JAXB to cross reference XmlIDs from two XML files

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

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

}

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

}

Leave a Comment