2010-07-19 13 views
19

वहाँ बदसूरत एक्सएमएल फ़ाइल है कि unmarshalled जा करने के लिए है:जावा/JAXB: Unmarshall एक्सएमएल विशिष्ट जावा ऑब्जेक्ट के लिए जिम्मेदार बताते हैं जिम्मेदार बताते हैं

<?xml version="1.0" ?> 
<configuration> 
    <section name="default_options"> 
     <value name="default_port">8081</value> 
     <value name="log_level">WARNING</value> 
    </section> 
    <section name="custom_options"> 
     <value name="memory">64M</value> 
     <value name="compatibility">yes</value> 
    </section> 
</configuration> 

परिणामस्वरूप जावा वस्तुओं होना चाहिए:

public class DefaultOptions { 
    private int defaultPort; 
    private String logLevel; 
    // etc... 
} 

public class CustomOptions { 
    private String memory; 
    private String compatibility; 
    // etc... 
} 

This सवाल का जवाब बहुत है बंद करें लेकिन मैं अंतिम समाधान नहीं समझ सकता।

+0

क्या आप परिणामस्वरूप जावा ऑब्जेक्ट्स को बदल नहीं सकते? IMHO यह बहुत आसान और क्लीनर होगा यदि आपने अभी एक्सएमएल संरचना का पालन किया है (या अपनी इच्छित संरचना का पालन करने के लिए इसे बदलें) –

+0

@ डिएगो डायस, वास्तव में नहीं। इन तरह पीओजेओ होना चाहिए। –

+0

क्या डिफॉल्टऑप्शन और कस्टम ऑप्शन में एक सामान्य सुपर क्लास जोड़ा जा सकता है? –

उत्तर

16

कैसे के बारे में?

परिचय एक आम सुपर वर्ग कहा जाता है विकल्प:

import javax.xml.bind.annotation.XmlAttribute; 

public abstract class Options { 

    private String name; 

    @XmlAttribute 
    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

} 
फिर विकल्प (इस उदाहरण में विन्यास) की सूची के साथ अपने वर्ग पर

, कि संपत्ति पर एक @XmlJavaTypeAdapter निर्दिष्ट करें:

import java.util.ArrayList; 
import java.util.List; 

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

@XmlRootElement 
public class Configuration { 

    private List<Options> section = new ArrayList<Options>(); 

    @XmlJavaTypeAdapter(OptionsAdapter.class) 
    public List<Options> getSection() { 
     return section; 
    } 

    public void setSection(List<Options> section) { 
     this.section = section; 
    } 

} 

XmlAdapter इस तरह कुछ दिखाई देगा:

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

public class OptionsAdapter extends XmlAdapter<AdaptedOptions, Options> { 

    @Override 
    public Options unmarshal(AdaptedOptions v) throws Exception { 
     if("default_options".equals(v.name)) { 
      DefaultOptions options = new DefaultOptions(); 
      options.setName(v.getName()); 
      options.setDefaultPort(Integer.valueOf(v.map.get("default_port"))); 
      options.setLogLevel(v.map.get("log_level")); 
      return options; 
     } else { 
      CustomOptions options = new CustomOptions(); 
      options.setName(v.getName()); 
      options.setCompatibility(v.map.get("compatibility")); 
      options.setMemory(v.map.get("memory")); 
      return options; 
     } 
    } 

    @Override 
    public AdaptedOptions marshal(Options v) throws Exception { 
     AdaptedOptions adaptedOptions = new AdaptedOptions(); 
     adaptedOptions.setName(v.getName()); 
     if(DefaultOptions.class == v.getClass()) { 
      DefaultOptions options = (DefaultOptions) v; 
      adaptedOptions.map.put("default_port", String.valueOf(options.getDefaultPort())); 
      adaptedOptions.map.put("log_level", options.getLogLevel()); 
     } else { 
      CustomOptions options = (CustomOptions) v; 
      adaptedOptions.map.put("compatibility", options.getCompatibility()); 
      adaptedOptions.map.put("memory", options.getMemory()); 
     } 
     return adaptedOptions; 
    } 

} 

AdaptedOption जैसा दिखता है:

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Map.Entry; 

import javax.xml.bind.Marshaller; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlValue; 

public class AdaptedOptions extends Options { 

    @XmlAttribute String name; 
    @XmlElement List<Value> value = new ArrayList<Value>(); 
    Map<String, String> map = new HashMap<String, String>(); 

    public void beforeMarshal(Marshaller marshaller) { 
     for(Entry<String, String> entry : map.entrySet()) { 
      Value aValue = new Value(); 
      aValue.name = entry.getKey(); 
      aValue.value = entry.getValue(); 
      value.add(aValue); 
     } 
    } 

    public void afterUnmarshal(Unmarshaller unmarshaller, Object parent) { 
     for(Value aValue : value) { 
      map.put(aValue.name, aValue.value); 
     } 
    } 

    private static class Value { 
     @XmlAttribute String name; 
     @XmlValue String value; 
    } 

} 
8

आप एक अलग वर्गों अपने XML की संरचना का प्रतिनिधित्व करने के लिए बना सकते हैं:

public class Section { 
    @XmlAttribute 
    public String name; 
    @XmlElement(name = "value") 
    public List<Value> values; 
} 

public class Value { 
    @XmlAttribute 
    public String name; 
    @XmlValue 
    public String value; 
} 

और फिर एक XmlAdapter रूपांतरण करने के लिए उपयोग करें:

public class OptionsAdapter extends XmlAdapter<Section, Options> { 
    public Options unmarshal(Section s) { 
     if ("default_options".equals(s.name)) { 
      ... 
     } else if (...) { 
      ... 
     } 
     ... 
    } 
    ... 
} 

@XmlElement 
public class Configuration { 
    @XmlElement(name = "section") 
    @XmlJavaTypeAdapter(OptionsAdapter.class) 
    public List<Options> options; 
} 

public class DefaultOptions extends Options { ... } 
public class CustomOptions extends Options { ... } 
+0

दिलचस्प समाधान। सबसे पहले, धन्यवाद। मैं इसे आजमाऊंगा। क्या समस्या हल करने का यही एकमात्र तरीका है? या शायद "if (" default_options ".equals (s.name)) के बिना थोड़ा और अधिक सुरुचिपूर्ण समाधान हैं"? –

+0

@ आर्टिम: चूंकि जेएक्सबी विशेषता मूल्य से लक्ष्य वर्ग को कम नहीं कर सकता है, इसलिए इसे किसी भी तरह के मैन्युअल डिप्चिंग की आवश्यकता होती है। बेशक, आप इसे अधिक अमूर्त तरीके से कर सकते हैं, उदा। विशेषता मानों से विकल्पों कारखानों में एक मानचित्र का उपयोग करें। – axtavt

संबंधित मुद्दे