2011-03-15 7 views
5

मैं दो अलग-अलग एक्सएमएल फाइलों से पीओजेओएस तक मार्शल/अनमशाल करने की कोशिश कर रहा हूं। पहले एक्सएमएल फ़ाइल इस तरह दिखता है:दो एक्सएमएल फाइलों से संदर्भ एक्सएमएलआईडीएस को पार करने के लिए जेएक्सबी का उपयोग

--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 टिप्पणियों का उपयोग करने, मैं सफलतापूर्वक सही नोड जो इसे का संदर्भ को इंगित करने के आर्क वर्गों को पॉप्युलेट कर सकते हैं।

हालांकि, मैं भी इस XML को पार्स करने के लिए है:

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

वर्तमान में, मेरी कार्यक्रम को सफलतापूर्वक नेटवर्क वस्तु unmarshals, लेकिन वहाँ है कि JAXB नोड्स है कि मौजूद "देख" करने की अनुमति देता नेटवर्क और NetworkInputs बीच कोई संबंध नहीं है नेटवर्क में। मैं चाहता हूं कि मेरी फ्लो ऑब्जेक्ट्स नेटवर्क क्लास में सही नोड को इंगित करें।

मैं मूल रूप से ऐसा करना चाहते हैं: 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 और यह सिर्फ काम नहीं करता, क्योंकि मैं अपने आबादी वाले नेटवर्क के लिए नोड डेटा एक स्थिर संदर्भ से नहीं मिल सकता है ।

क्या ऐसा कुछ भी करना संभव है?

उत्तर

8

यह एक एक्सएमएलएडाप्टर के साथ किया जा सकता है। चाल XmlAdapter Unmarshaller NetworkInputs.xml के साथ इस्तेमाल किया करने के लिए Network.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 साथ प्रवाह पर toNode संपत्ति मैप करने के लिए है :

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 को नोड्स जानता है पारित करेंगे है:

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

} 
+0

यह काम किया। शुक्रिया, यह सच में सराहनीय है! –

+1

ग्रेट ग्रेट आइडिया, आपको इसे अपने ब्लॉग में पोस्ट करना चाहिए। – ekeren

0

मेरे समाधान: आईडी संकल्प एक (दुर्भाग्य से) आंतरिक वर्ग (com.sun.xml द्वारा नियंत्रित किया जाता। internal.bind.IDResolver) जिसे बाहरी से सेट किया जा सकता है।

final Unmarshaller unmarshaller = context.createUnmarshaller(); 
unmarshaller.setProperty(IDResolver.class.getName(), resolver); 

जहां निर्णायक के कई उदाहरणों पर संकल्प का उपयोग किया जा सकता है। लेकिन मुद्दा यह है कि समाधानकर्ता startDocument पर itsself साफ़ नहीं होगी com.sun.xml.internal.bind.v2.runtime.unmarshaller.DefaultIDResolver के डिफ़ॉल्ट कार्यान्वयन करता है:

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 { 
    public static final class CallableImplementation implements Callable<Object> { 
     private final Object value; 

     private CallableImplementation(final Object value) { 
      this.value = value; 
     } 

     @Override 
     public Object call() { 
      return value; 
     } 
    } 

    private final Map<KeyAndClass, Object> m = new HashMap<KeyAndClass, Object>(); 

    @SuppressWarnings("rawtypes") 
    @Override 
    public synchronized CallableImplementation resolve(final String key0, final Class clazz) throws SAXException { 
     assert clazz != null; 
     assert key0 != null; 
     final KeyAndClass key = new KeyAndClass(clazz, key0); 
     final Object value = m.get(key); 
     return new CallableImplementation(value); 
    } 

    static class KeyAndClass { 
     public final Class<?> clazz; 
     public final String key; 

     public KeyAndClass(final Class<?> clazz, final String key) { 
      this.clazz = clazz; 
      this.key = key; 
     } 

     @Override 
     public int hashCode() { 
      final int prime = 31; 
      int result = 1; 
      result = prime * result + clazz.hashCode(); 
      result = prime * result + key.hashCode(); 
      return result; 
     } 

     @Override 
     public boolean equals(Object obj) { 
      if (this == obj) { 
       return true; 
      } 
      if (obj == null) { 
       return false; 
      } 
      if (getClass() != obj.getClass()) { 
       return false; 
      } 
      final KeyAndClass other = (KeyAndClass) obj; 
      if (!clazz.equals(other.clazz)) { 
       return false; 
      } 
      if (!key.equals(other.key)) { 
       return false; 
      } 
      return true; 
     } 

    } 

    @Override 
    public synchronized void bind(final String key0, final Object value) throws SAXException { 
     assert key0 != null; 
     assert value != null; 
     Class<? extends Object> clazz = value.getClass(); 
     assert clazz != null; 
     final KeyAndClass key = new KeyAndClass(clazz, key0); 
     final Object oldValue = m.put(key, value); 
     if (oldValue != null) { 
      final String message = MessageFormat.format("duplicated key ''{0}'' => ''{1}'' - old: ''{2}''", key, value, 
        oldValue); 
      throw new AssertionError(message); 
     } 
    } 
} 
संबंधित मुद्दे