与Adding an XML attribute depending on an Option相关,我想根据选项在Scala中添加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>
我想根据选项生成很多标签,我想知道是否可以找到更简洁的解决方案。例如,拉着Elem班的?运算符并使用它(这是一个肮脏的解决方案,因为在调用?运算符之前,Option value2被转换为String):
scala> def toXml2(value1: String, value2: Option[String]) =
| <body>
| <tag1>{value1}</tag1>
| {<tag2>{value2}</tag2>?}
| </body>
有什么想法吗?
答案 0 :(得分: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>
将导致:
<body>
<tag1>Hello</tag1>
<tag3><innerTag></innerTag></tag3>
<tag4><innerTag></innerTag></tag4>
</body>
答案 1 :(得分:6)
为什么不使用这样的if语句:
def toXml(value1:String,value2:Option[String]) =
<body>
<tag1>{value1}</tag1>
{if (value2 isDefined) <tag2>{value2.get}</tag2>}
</body>
这应该可以解决问题并且是可以理解的,对吧?
答案 2 :(得分:3)
您还可以fold
选项:
{ value2.fold(NodeSeq.Empty)(x => <tag2>{x}</tag2>) }
答案 3 :(得分:2)
这是一个简单的版本,不使用(可以说是误导,因为没有积累)折叠方法:
if (!oops_flag) {
var speed = (score===1) ? 70 : 100;
timerID = setTimeout(dotime, speed);
}
结果与佐尔坦的答案相同。