使用JAXB交叉引用来自两个XML文件的XmlID

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


--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类以指向其引用的正确Node。


但是,我还必须解析此XML:


--NetworkInputs.xml--

<NetworkInputs>

  <Flows>

    <Flow toNode="JND" />

    <Flow toNode="ROD" />

  </Flows>

</NetworkInputs>

------

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


我基本上想这样做: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 ,但它不起作用,因为我无法从中获取填充网络的Node数据。静态上下文。


甚至可以做这样的事情吗?


智慧大石
浏览 567回答 2
2回答

暮色呼如

可以使用XmlAdapter完成。诀窍是XmlAdapter将需要使用Network.xml中的所有节点进行初始化,并传递给与NetworkInputs.xml一起使用的Unmarshaller:import java.io.File;import javax.xml.bind.JAXBContext;import javax.xml.bind.Marshaller;import javax.xml.bind.Unmarshaller;public class Demo {&nbsp; &nbsp; public static void main(String[] args) throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; JAXBContext jc = JAXBContext.newInstance(Network.class, NetworkInputs.class);&nbsp; &nbsp; &nbsp; &nbsp; File networkXML = new File("Network.xml");&nbsp; &nbsp; &nbsp; &nbsp; Unmarshaller unmarshaller = jc.createUnmarshaller();&nbsp; &nbsp; &nbsp; &nbsp; Network network = (Network) unmarshaller.unmarshal(networkXML);&nbsp; &nbsp; &nbsp; &nbsp; File networkInputsXML = new File("NetworkInputs.xml");&nbsp; &nbsp; &nbsp; &nbsp; Unmarshaller unmarshaller2 = jc.createUnmarshaller();&nbsp; &nbsp; &nbsp; &nbsp; NodeAdapter nodeAdapter = new NodeAdapter();&nbsp; &nbsp; &nbsp; &nbsp; for(Node node : network.getNodes()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nodeAdapter.getNodes().put(node.getId(), node);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; unmarshaller2.setAdapter(nodeAdapter);&nbsp; &nbsp; &nbsp; &nbsp; NetworkInputs networkInputs = (NetworkInputs) unmarshaller2.unmarshal(networkInputsXML);&nbsp; &nbsp; &nbsp; &nbsp; Marshaller marshaller = jc.createMarshaller();&nbsp; &nbsp; &nbsp; &nbsp; marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);&nbsp; &nbsp; &nbsp; &nbsp; marshaller.marshal(networkInputs, System.out);&nbsp; &nbsp; }}诀窍是使用XmlAdapter在Flow上映射toNode属性:import javax.xml.bind.annotation.XmlAttribute;import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;public class Flow {&nbsp; &nbsp; private Node toNode;&nbsp; &nbsp; @XmlAttribute&nbsp; &nbsp; @XmlJavaTypeAdapter(NodeAdapter.class)&nbsp; &nbsp; public Node getToNode() {&nbsp; &nbsp; &nbsp; &nbsp; return toNode;&nbsp; &nbsp; }&nbsp; &nbsp; public void setToNode(Node toNode) {&nbsp; &nbsp; &nbsp; &nbsp; this.toNode = toNode;&nbsp; &nbsp; }}该适配器将如下所示。诀窍是,我们会将知道所有节点的已配置XmlAdapter传递给解组器:import java.util.HashMap;import java.util.Map;import javax.xml.bind.annotation.adapters.XmlAdapter;public class NodeAdapter extends XmlAdapter<String, Node>{&nbsp; &nbsp; private Map<String, Node> nodes = new HashMap<String, Node>();&nbsp; &nbsp; public Map<String, Node> getNodes() {&nbsp; &nbsp; &nbsp; &nbsp; return nodes;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public Node unmarshal(String v) throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; return nodes.get(v);&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public String marshal(Node v) throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; return v.getId();&nbsp; &nbsp; }}

慕无忌1623718

我的解决方案:ID解析由一个(不幸的)内部类(com.sun.xml.internal.bind.IDResolver)处理,该内部类可以从外部进行设置。final Unmarshaller unmarshaller = context.createUnmarshaller();unmarshaller.setProperty(IDResolver.class.getName(), resolver);可以在解组器的许多实例上使用解析器的地方。但是关键是,解析程序不会像com.sun.xml.internal.bind.v2.runtime.unmarshaller.DefaultIDResolver的默认实现那样在startDocument上清除自身:import java.text.MessageFormat;import java.util.HashMap;import java.util.Map;import java.util.concurrent.Callable;import org.xml.sax.SAXException;import com.sun.xml.internal.bind.IDResolver;public final class IDResolverExtension extends IDResolver {&nbsp; &nbsp; public static final class CallableImplementation implements Callable<Object> {&nbsp; &nbsp; &nbsp; &nbsp; private final Object value;&nbsp; &nbsp; &nbsp; &nbsp; private CallableImplementation(final Object value) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.value = value;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; public Object call() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return value;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; private final Map<KeyAndClass, Object> m = new HashMap<KeyAndClass, Object>();&nbsp; &nbsp; @SuppressWarnings("rawtypes")&nbsp; &nbsp; @Override&nbsp; &nbsp; public synchronized CallableImplementation resolve(final String key0, final Class clazz) throws SAXException {&nbsp; &nbsp; &nbsp; &nbsp; assert clazz != null;&nbsp; &nbsp; &nbsp; &nbsp; assert key0 != null;&nbsp; &nbsp; &nbsp; &nbsp; final KeyAndClass key = new KeyAndClass(clazz, key0);&nbsp; &nbsp; &nbsp; &nbsp; final Object value = m.get(key);&nbsp; &nbsp; &nbsp; &nbsp; return new CallableImplementation(value);&nbsp; &nbsp; }&nbsp; &nbsp; static class KeyAndClass {&nbsp; &nbsp; &nbsp; &nbsp; public final Class<?> clazz;&nbsp; &nbsp; &nbsp; &nbsp; public final String key;&nbsp; &nbsp; &nbsp; &nbsp; public KeyAndClass(final Class<?> clazz, final String key) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.clazz = clazz;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.key = key;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; public int hashCode() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final int prime = 31;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int result = 1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = prime * result + clazz.hashCode();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = prime * result + key.hashCode();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return result;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; public boolean equals(Object obj) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (this == obj) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (obj == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (getClass() != obj.getClass()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final KeyAndClass other = (KeyAndClass) obj;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!clazz.equals(other.clazz)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!key.equals(other.key)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public synchronized void bind(final String key0, final Object value) throws SAXException {&nbsp; &nbsp; &nbsp; &nbsp; assert key0 != null;&nbsp; &nbsp; &nbsp; &nbsp; assert value != null;&nbsp; &nbsp; &nbsp; &nbsp; Class<? extends Object> clazz = value.getClass();&nbsp; &nbsp; &nbsp; &nbsp; assert clazz != null;&nbsp; &nbsp; &nbsp; &nbsp; final KeyAndClass key = new KeyAndClass(clazz, key0);&nbsp; &nbsp; &nbsp; &nbsp; final Object oldValue = m.put(key, value);&nbsp; &nbsp; &nbsp; &nbsp; if (oldValue != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final String message = MessageFormat.format("duplicated key ''{0}'' => ''{1}'' - old: ''{2}''", key, value,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oldValue);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new AssertionError(message);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java