Related to Adding an XML attribute depending on an Option, I would like to add a XML tag in Scala depending on an option.
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
If the Option exists:
scala> toXml("value1", Some("value2"))
res1: scala.xml.Elem =
<body>
<tag1>value1</tag1>
<tag2>value2</tag2>
</body>
If the Option does not exist:
scala> toXml("value1", None)
res2: scala.xml.Elem =
<body>
<tag1>value1</tag1>
</body>
I want to generate a lot of tags depending on an Option, I was wondering whether a more concise solution could be found. For instance, pimping the Elem class with the ? operator and use it like this (it is a dirty solution since the Option value2 is converted to a String before the ? operator is called):
scala> def toXml2(value1: String, value2: Option[String]) =
| <body>
| <tag1>{value1}</tag1>
| {<tag2>{value2}</tag2>?}
| </body>
Any thoughts?
Your desired ?
function can be realised like this:
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
}
}
}
For simplicity this is only for single childed nodes to show you the concept (I guess you should be able to write a more general function from there in case you need it)
If the implicit function is in scope, the ?
operator can be used just like you wanted:
<body>
{ <tag1>{ Some("Hello") }</tag1>? }
{ <tag2>{ None }</tag2>? }
{ <tag3>{ Some(<innerTag/>) }</tag3>? }
{ <tag4><innerTag/></tag4>? }
{ <tag5>{ None }</tag5>? }
</body>
will result in:
<body>
<tag1>Hello</tag1>
<tag3><innerTag></innerTag></tag3>
<tag4><innerTag></innerTag></tag4>
</body>
Why not use an if statement like this:
def toXml(value1:String,value2:Option[String]) =
<body>
<tag1>{value1}</tag1>
{if (value2 isDefined) <tag2>{value2.get}</tag2>}
</body>
That should do the trick and is fairly understandable, right?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With