2011-01-12 10 views
14

में मैं स्काला और XML के बीच मार्शलिंग/unmarshalling डेटा के लिए विभिन्न दृष्टिकोण से देख रहा हूँ, और मैं समुदाय प्रतिक्रिया (अधिमानतः पहले हाथ ज्ञान/अनुभव पर आधारित) प्राप्त करने में दिलचस्पी रखता हूँ।मार्शलिंग/unmarshalling एक्सएमएल स्काला

हम वर्तमान में JAXB, जो ठीक है का उपयोग कर रहे हैं, लेकिन मैं एक शुद्ध स्काला समाधान के लिए उम्मीद कर रहा हूँ। मैं निम्नलिखित दृष्टिकोण पर विचार कर रहा हूँ:

  1. उपयोग स्काला के निर्मित एक्सएमएल सुविधाओं: Scala-> एक्सएमएल आसान होगा, लेकिन मेरा अनुमान है कि दूसरी दिशा काफी दर्दनाक होगा। दूसरी तरफ, यह दृष्टिकोण मनमाने ढंग से अनुवाद तर्क का समर्थन करता है।

  2. बाध्यकारी डाटा: scalaxb पल में कुछ हद तक अपरिपक्व प्रतीत हो रहा है और हमारे वर्तमान स्कीमा प्रबंधन नहीं करती है, और मैं स्काला के लिए बाध्यकारी पुस्तकालय किसी भी अन्य डेटा का पता नहीं है। जेएक्सबी की तरह, शामिल परिवर्तनों का समर्थन करने के लिए एक अतिरिक्त अनुवाद परत की आवश्यकता होती है।

  3. एक्सएमएल पिकलर combinators: GData Scala Client पुस्तकालय एक्सएमएल पिकलर combinators प्रदान करता है, लेकिन हाल के परियोजना गतिविधि कम कर दिया गया है और मैं नहीं जानता कि वर्तमान स्थिति क्या है।

सवाल:

  1. क्या दृष्टिकोण/पुस्तकालयों के साथ अपने अनुभवों को मैं सूचीबद्ध किया है कर रहे हैं?
  2. प्रत्येक के सापेक्ष फायदे और नुकसान क्या हैं?
  3. वहाँ किसी भी अन्य तरीकों या स्काला पुस्तकालयों है कि मैं पर विचार करना चाहिए रहे हैं?

संपादित करें:

मैं इस सवाल का मेरे अपने जवाब में पिकलर combinators की मेरी प्रारंभिक छापों पर कुछ नोट जोड़ा है, लेकिन मैं अभी भी बहुत कोई है जो वास्तव में विभिन्न दृष्टिकोण जानता है से प्रतिक्रिया में दिलचस्पी रखता हूँ गहराई में मैं जो उम्मीद कर रहा हूं वह कुछ हद तक व्यापक तुलना है जो डेवलपर्स को उनकी ज़रूरतों के लिए सही दृष्टिकोण चुनने में मदद करेगा।

+1

यदि आप मुझे स्कीमा भेज सकते हैं (gmail पर eed3si9n), तो मैं scalaxb को ठीक करने में सक्षम हो सकता हूं। –

उत्तर

5

मैं स्काला के अंतर्निहित एक्सएमएल सुविधाओं का उपयोग करें।

val bodyXML = <body><segment uri="foo"><segment uri="bar" /></segment></body> 

ध्यान दें कि खंडों एक दूसरे के भीतर नेस्ट किया जा सकता है: मैं बस एक दस्तावेज़ संरचना है कि इस तरह दिखता है के लिए अक्रमांकन क्रियान्वित किया है।

एक खंड इस प्रकार लागू किया गया है:

case class Segment(uri: String, children: Seq[Segment]) 

एक्सएमएल deserialize करने के लिए, आप यह करते हैं:

val mySegments = topLevelSegments(bodyXML) 

... और topLevelSegments के कार्यान्वयन सिर्फ कोड की कुछ लाइनें है।

def topLevelSegments(bodyXML: Node): Seq[Segment] = 
    (bodyXML \ "segment") map { nodeToSegment } 

def nodeToSegment = (n: Node) => Segment((n \ "@uri")(0) text, childrenOf(n)) 

def childrenOf(n: Node): Seq[Segment] = (n \ "segment") map { nodeToSegment } 

आशा है कि मदद करता है: प्रत्यावर्तन, जो XML संरचना के माध्यम से खोदता है ध्यान दें।

+0

मुझे लगता है कि यह दृष्टिकोण बालों जैसा नहीं है जैसा कि मैंने उम्मीद की थी, लेकिन मुझे आश्चर्य है कि यह एक और जटिल स्कीमा को स्केल करने और समय के साथ बनाए रखने के लिए कितना आसान है। डेटा बाइंडिंग और पिकलर संयोजकों दोनों का एक निश्चित लाभ यह है कि आप एक साथ क्रमबद्धता/deserialization निर्दिष्ट करते हैं ताकि आपको कोड के दो समानांतर निकायों को बनाए रखने की चिंता न करें। –

+2

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

-1

एक scala.xml लिखना। स्ट्रिंग में नोड एक बड़ा सौदा नहीं है। PrettyPrinter आपको अपनी जरूरतों का ख्याल रखना चाहिए। scala.xml.XML.save() एक फ़ाइल और scala.xml.XML.write() आउटपुट को Writer पर लिख देगा।

+2

उत्तर देने के लिए धन्यवाद, लेकिन यह वही नहीं है जो मैं ढूंढ रहा था। मुझे XML दस्तावेज़ों और डोमेन-विशिष्ट ऑब्जेक्ट मॉडल के बीच रूपांतरण में रूचि है। –

4

तुलना के लिए, मैं GData Scala Client पुस्तकालय से पिकलर combinators का उपयोग कर David's example कार्यान्वित:

def segment: Pickler[Segment] = 
    wrap(elem("segment", 
      attr("uri", text) 
      ~ rep(segment))) { // rep = zero or more repetitions 
     // convert (uri ~ children) to Segment(uri, children), for unpickling 
     Segment.apply 
    } { 
     // convert Segment to (uri ~ children), for pickling 
     (s: Segment) => new ~(s.uri, s.children toList) 
    } 

def body = elem("body", rep(segment)) 

case class Segment(uri: String, children: List[Segment]) 

इस कोड को वह सब Segment रों और XML के बीच अनुवाद के दोनों दिशाओं निर्दिष्ट करने के लिए आवश्यक है, एक समान राशि जबकि है स्कैला एक्सएमएल लाइब्रेरी का उपयोग करते समय कोड का अनुवाद केवल एक दिशा निर्दिष्ट करता है। मेरी राय में, यह संस्करण समझना भी आसान है (एक बार जब आप पिकलर डीएसएल जानते हैं)। बेशक, जैसा कि डेविड ने एक टिप्पणी में बताया, इस दृष्टिकोण के लिए एक अतिरिक्त निर्भरता और एक अन्य डीएसएल की आवश्यकता है जिसे डेवलपर्स से परिचित होना चाहिए।

सेगमेंट में अनुवाद एक्सएमएल

तरह
xml.XML.save(filename, body.pickle(segments, PlainOutputStore.empty).rootNode) 

जहां तक ​​Combinator पुस्तकालय का संबंध है, यह और सभ्य आकार में हो रहा है दूसरी तरह लग रहा है के रूप में सरल

body.unpickle(LinearStore.fromFile(filename)) // returns a PicklerResult[List[Segment]] 

के रूप में और अनुवाद है स्कैला 2.8.1 में संकलित करता है। मेरी प्रारंभिक छाप यह है कि पुस्तकालय में कुछ नस्लों (उदा। oneOrMore संयोजक) गायब है, जिसे काफी आसानी से उपचार किया जा सकता है। मेरे पास यह देखने का समय नहीं है कि यह खराब इनपुट को कितनी अच्छी तरह से संभालता है, लेकिन अब तक यह मेरी आवश्यकताओं के लिए पर्याप्त दिखता है।

+0

"एक या अधिक" क्या वह नहीं है 'rep1' करता है? – soc

+0

@soc मुझे लगता है कि आप मानक पुस्तकालय में 'rep1' पार्सर संयोजक का जिक्र कर रहे हैं। दुर्भाग्यवश, एक्सएमएल पिकलर लाइब्रेरी में ऐसा कोई संयोजक नहीं है। –