2012-02-23 13 views
11

स्थितिमामूली बदलाव

मैं स्कीमा कि एक दूसरे के बीच केवल भिन्न के आधार पर XML दस्तावेज़ों पैदा समर्थन करने की आवश्यकता के साथ स्कीमा का समर्थन करने के JAXB का उपयोग करना। विशेष रूप से, जिन स्कीमा को मुझे समर्थन देने की आवश्यकता है वे उद्योग मानकों पर आधारित हैं जो समय के साथ थोड़ा बदलते हैं और विक्रेता अपने स्वयं के अनुकूलित संस्करण बना सकते हैं।

समस्या

मैं विरासत के साथ एक समाधान के रूप JAXB 2 (मेट्रो से) का उपयोग करने के लिए इच्छुक था।

com.company.xml.schema.v1 
    com.company.xml.schema.v2 
    com.company.xml.schema.v2.vendorxyz 

कहाँ वी 2 पैकेज में कक्षाएं बस v1 पैकेज में कक्षाओं का विस्तार करने और आवश्यक के रूप में ओवरराइड होगा: मैं कुछ इस तरह खत्म करने के लिए पैकेज संरचना की उम्मीद। दुर्भाग्यवश, यह योजना असंभव हो गई क्योंकि उप-वर्ग अभिभावक वर्गों (see here) में एनोटेशन को ओवरराइट नहीं कर सकता है। उदाहरण के लिए, यदि स्कीमा में एक विशेषता का नाम बदलकर संस्करणों के बीच बदल दिया गया था, तो v2 तत्व वर्ग को v1 से विरासत के बिना तत्व को पूरी तरह से पुन: कार्यान्वित करना होगा।

तो यह है कि केवल दो विकल्पों के साथ मुझे छोड़ देता है जहाँ तक मैं, बता सकते हैं

विकल्प 1

प्रत्येक स्कीमा प्रकार के लिए एक "आधार" पैकेज बनाएं साथ @ कि पैकेज में एलीमेंट क्लास व्याख्या XmlAccessorType (XmlAccessType.NONE), और अन्य सभी एनोटेशन हटा दें। फिर, प्रत्येक संस्करण वाले पैकेज में कक्षाएं बनाते हैं जो "बेस" पैकेज में संबंधित वर्ग को उप-वर्ग बनाते हैं और सभी आवश्यक एनोटेशन जोड़ते हैं। यह समाधान मुझे विरासत क्षेत्र में थोड़ी मदद देता है, लेकिन कोड डुप्लिकेशन बहुत बड़ा है और इसे बनाए रखना एक चुनौती होगी।

विकल्प 2

JAXB प्रयोग न करें। मुझे वास्तव में यह समाधान पसंद नहीं है क्योंकि मैं जेएक्स-आरएस/जेएक्स-डब्ल्यूएस के साथ भी काम करना चाहता हूं।

प्रश्न

  • मैं कैसे आदेश मामूली बदलाव के साथ एकाधिक स्कीमा का समर्थन करने के JAXB का उपयोग करना चाहिए, कोड दोहराव का एक समूह के बिना?
  • क्या कोई अलग तकनीक संयोजन है जिसे मुझे देखना चाहिए?

संपादित

ब्लेज से नीचे समाधान हमारे स्कीमा जो आम तौर पर एक ही डेटा के साथ एक दूसरे का सिर्फ एक छोटी सी अनुवाद थे के अधिकांश के लिए पूरी तरह से काम किया। हालांकि, हम उन मामलों में एक समस्या में भाग गए जहां संस्करण के लिए पैकेज नामों के साथ विरासत का उपयोग करने के लिए यह अधिक समझ में आया। उदाहरण के लिए:

com.company.xml.schema.v1.ElementA 
com.company.xml.schema.v2.ElementA 

(जहां v2.ElementA फैली v1.ElementA)

इस मामले में MOXY के OXM का उपयोग करते हुए एक बग भर में लड़खड़ाती है और वैकल्पिक हल here पाया जा सकता है (ब्लेज, द्वारा प्रदान की समाधान के साथ कोई कम से!)

उत्तर

5

नोट: मैं EclipseLink JAXB (MOXy) लीड और JAXB 2 (JSR-222) विशेषज्ञ समूह का सदस्य हूं।

आप XML स्कीमा के बीच विविधताओं को मैप करने के लिए एक्लिप्ससेंक जेएक्सबी में बाहरी बाध्यकारी दस्तावेज़ का उपयोग कर सकते हैं।

वेंडर 1

आप मानक JAXB एनोटेशन इस्तेमाल कर सकते हैं विक्रेताओं में से एक मैप करने के लिए:

package forum9419732; 

import javax.xml.bind.annotation.*; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Customer { 

    @XmlAttribute 
    private int id; 

    private String lastName; 
    private String firstName; 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public String getLastName() { 
     return lastName; 
    } 

    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 

    public String getFirstName() { 
     return firstName; 
    } 

    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 

} 

विक्रेता 2

हम अनुकूलित करने के लिए MOXY के बाहरी मेटाडाटा का उपयोग करेगा एनोटेशन द्वारा प्रदान किया गया मेटाडाटा। दस्तावेज़ (oxm-v2.xml) एक्सएमएल गुण के लिए नीचे हम firstName और lastName गुण नक्शा होगा:

<?xml version="1.0"?> 
<xml-bindings 
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" 
    package-name="forum9419732"> 
    <java-types> 
     <java-type name="Customer"> 
      <java-attributes> 
       <xml-attribute java-attribute="firstName"/> 
       <xml-attribute java-attribute="lastName"/> 
      </java-attributes> 
     </java-type> 
    </java-types> 
</xml-bindings> 

विक्रेता 3

फिर हम MOXY के बाहरी बाध्यकारी दस्तावेज़ (OXM-v3.xml) का उपयोग करेगा करने के लिए

एनोटेशन ओवरराइड करें। इस बार हम id संपत्ति को एक्सएमएल तत्व बना देंगे। नीचे

<?xml version="1.0"?> 
<xml-bindings 
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" 
    package-name="forum9419732"> 
    <java-types> 
     <java-type name="Customer"> 
      <java-attributes> 
       <xml-element java-attribute="id" name="identifier"/> 
      </java-attributes> 
     </java-type> 
    </java-types> 
</xml-bindings> 

डेमो

नमूना कोड बाहरी मेटाडाटा निर्दिष्ट करने के लिए यह दर्शाता है। ध्यान दें कि मैंने चौथा विक्रेता कैसे पेश किया ताकि यह दिखाया जा सके कि बाहरी मेटाडेटा दस्तावेज़ संयुक्त किए जा सकते हैं।

package forum9419732; 

import java.util.*; 
import javax.xml.bind.*; 
import org.eclipse.persistence.jaxb.JAXBContextFactory; 

public class Demo { 

    public static void main(String[] args) throws JAXBException { 
     Customer customer = new Customer(); 
     customer.setId(123); 
     customer.setFirstName("Jane"); 
     customer.setLastName("Doe"); 

     // VENDOR 1 
     JAXBContext jcV1 = JAXBContext.newInstance(Customer.class); 
     marshal(jcV1, customer); 

     // VENDOR 2 
     Map<String, Object> propertiesV2 = new HashMap<String, Object>(1); 
     propertiesV2.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum9419732/oxm-v2.xml"); 
     JAXBContext jcV2 = JAXBContext.newInstance(new Class[] {Customer.class}, propertiesV2); 
     marshal(jcV2, customer); 

     // VENDOR 3 
     Map<String, Object> propertiesV3 = new HashMap<String, Object>(1); 
     propertiesV3.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum9419732/oxm-v3.xml"); 
     JAXBContext jcV3 = JAXBContext.newInstance(new Class[] {Customer.class}, propertiesV3); 
     marshal(jcV3, customer); 

     // VENDOR 4 
     Map<String, Object> propertiesV4 = new HashMap<String, Object>(1); 
     List<String> oxmV4 = new ArrayList<String>(2); 
     oxmV4.add("forum9419732/oxm-v2.xml"); 
     oxmV4.add("forum9419732/oxm-v3.xml"); 
     propertiesV4.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, oxmV4); 
     JAXBContext jcV4 = JAXBContext.newInstance(new Class[] {Customer.class}, propertiesV4); 
     marshal(jcV4, customer); 
    } 

    private static void marshal(JAXBContext jc, Customer customer) throws JAXBException { 
     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(customer, System.out); 
     System.out.println(); 
    } 

} 

आउटपुट

नीचे विक्रेताओं में से प्रत्येक से उत्पादन होता है। याद रखें कि Customer का एक ही उदाहरण इन XML दस्तावेज़ों में से प्रत्येक को बनाने के लिए उपयोग किया गया था।

<?xml version="1.0" encoding="UTF-8"?> 
<customer id="123"> 
    <lastName>Doe</lastName> 
    <firstName>Jane</firstName> 
</customer> 

<?xml version="1.0" encoding="UTF-8"?> 
<customer id="123" lastName="Doe" firstName="Jane"/> 

<?xml version="1.0" encoding="UTF-8"?> 
<customer> 
    <identifier>123</identifier> 
    <lastName>Doe</lastName> 
    <firstName>Jane</firstName> 
</customer> 

<?xml version="1.0" encoding="UTF-8"?> 
<customer lastName="Doe" firstName="Jane"> 
    <identifier>123</identifier> 
</customer> 

अधिक जानकारी के लिए

+1

आप इस सवाल का जवाब और नमूने के लिए बहुत बहुत धन्यवाद। जैसा कि आपने सुझाव दिया है और मैं बहुत शक्तिशाली होने के लिए बाह्य मेटाडेटा समर्थन ढूंढ रहा हूं, मैं MOXy के JAXB कार्यान्वयन में स्थानांतरित हो गया हूं। – Terence

+1

धन्यवाद, इससे मेरी मदद मिली। बस एक बात: रिलीज 2.4 के रूप में, 'JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY' को' JAXBContextProperties.OXM_METADATA_SOURCE' द्वारा प्रतिस्थापित किया गया है। – DLight

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