2011-03-08 6 views
6

Adding an XML attribute depending on an Option से संबंधित, मैं एक विकल्प के आधार पर स्कैला में एक एक्सएमएल टैग जोड़ना चाहता हूं।स्कैला में किसी विकल्प के आधार पर, मैं XML टैग कैसे जोड़ूं या नहीं?

scala> def toXml(value1: String, value2: Option[String]) = 
    | <body> 
    | <tag1>{value1}</tag1> 
    | {value2 map (x => <tag2>{x}</tag2>) flatten} 
    | </body> 
toXml: (value1: String,value2: Option[String])scala.xml.Elem 

ऑप्शन मौजूद है:

scala> toXml("value1", Some("value2")) 
res1: scala.xml.Elem = 
<body> 
    <tag1>value1</tag1> 
    <tag2>value2</tag2> 
</body> 

, तो विकल्प मौजूद नहीं है:

scala> toXml("value1", None) 
res2: scala.xml.Elem = 
<body> 
    <tag1>value1</tag1> 

</body> 

मैं एक विकल्प के आधार पर टैग का एक बहुत उत्पन्न करना चाहते हैं, मैं सोच रहा था कि क्या एक और संक्षिप्त समाधान पाया जा सकता है। उदाहरण के लिए, एलेम क्लास के साथ पंपिंग? ऑपरेटर और इस तरह इसका इस्तेमाल (? यह है विकल्प मान 2 के बाद से एक गंदा समाधान से पहले एक स्ट्रिंग में बदल जाती है ऑपरेटर कहा जाता है):

scala> def toXml2(value1: String, value2: Option[String]) = 
    | <body> 
    | <tag1>{value1}</tag1> 
    | {<tag2>{value2}</tag2>?} 
    | </body> 

किसी भी विचार?

उत्तर

11

आपका वांछित ? समारोह इस तरह महसूस किया जा सकता:

implicit def optionElem(e: Elem) = new { 
    def ? : NodeSeq = { 
    require(e.child.length == 1) 
    e.child.head match { 
     case atom: Atom[Option[_]] => atom.data match { 
     case None => NodeSeq.Empty 
     case Some(x) => e.copy(child = x match { 
      case n: NodeSeq => n 
      case x => new Atom(x) 
     }) 
     } 
     case _ => e 
    }  
    } 
} 

सरलता के लिए यह है एक childed नोड्स आप अवधारणा को दिखाने के लिए केवल के लिए (मुझे लगता है कि तुम वहाँ से एक अधिक सामान्य समारोह में लिखने के लिए सक्षम होना चाहिए मामले में आप इसकी आवश्यकता है)

निहित समारोह दायरे में है, तो ? ऑपरेटर इस्तेमाल किया जा सकता, जैसा कि आपने चाहता था:

<body> 
{ <tag1>{ Some("Hello") }</tag1>? } 
{ <tag2>{ None }</tag2>? } 
{ <tag3>{ Some(<innerTag/>) }</tag3>? } 
{ <tag4><innerTag/></tag4>? } 
{ <tag5>{ None }</tag5>? } 
</body> 
,210

परिणाम देगा में:

<body> 
    <tag1>Hello</tag1> 

    <tag3><innerTag></innerTag></tag3> 
    <tag4><innerTag></innerTag></tag4> 

</body> 
6

एक इस तरह बयान करता है, तो क्यों उपयोग नहीं:

def toXml(value1:String,value2:Option[String]) = 
    <body> 
    <tag1>{value1}</tag1> 
    {if (value2 isDefined) <tag2>{value2.get}</tag2>} 
    </body> 

यही चाल करते हैं और काफी समझ में आता है, सही है चाहिए?

+1

धन्यवाद उत्तर के लिए ऐनी, यह स्पष्ट है कि मेरे मानचित्र का उपयोग और फ़्लैटन। हालांकि मैं प्रतिलिपि बनाने और चिपकाने से बचाना चाहता हूं, प्रत्येक विकल्प के लिए परिभाषित परीक्षण है। मैं एक समाधान की तलाश में हूं जहां कोड लगभग एक्सएमएल आउटपुट की तरह दिखता है। –

3

तुम भी fold विकल्प कर सकते हैं:

{ value2.fold(NodeSeq.Empty)(x => <tag2>{x}</tag2>) } 
+0

यह अन्य उत्तरों की तुलना में आसान है। – Casey

2

यहाँ (के बाद से कुछ भी नहीं जमा किया जा रहा है, यकीनन भ्रामक) एक सरल संस्करण है कि का उपयोग नहीं करता है गुना विधि:

value2.map(x => <tag2>{x}</tag>).getOrElse(NodeSeq.Empty) 

परिणाम हालांकि ज़ोलटन के उत्तर जैसा ही है।

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