根据Scala中的选项,如何添加XML标记?
与之相关,我想根据一个选项在Scala中添加一个XML标记根据Scala中的选项,如何添加XML标记?,xml,scala,Xml,Scala,与之相关,我想根据一个选项在Scala中添加一个XML标记 scala> def toXml(value1: String, value2: Option[String]) = | <body> | <tag1>{value1}</tag1> | {value2 map (x => <tag2>{x}</tag2>) flatten} | </body> toXml
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>def-toXml(value1:String,value2:Option[String])=
|
|{value1}
|{value2映射(x=>{x})展平}
|
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”,一些(“value2”))
res1:scala.xml.Elem=
价值1
价值2
如果该选项不存在:
scala> toXml("value1", None)
res2: scala.xml.Elem =
<body>
<tag1>value1</tag1>
</body>
scala>toXml(“值1”,无)
res2:scala.xml.Elem=
价值1
我想根据一个选项生成很多标记,我想知道是否可以找到更简洁的解决方案。例如,使用?运算符,并像这样使用它(这是一个肮脏的解决方案,因为在调用?运算符之前,选项value2已转换为字符串):
scala>def-toXml2(值1:String,值2:Option[String])=
|
|{value1}
|{{value2}?}
|
有什么想法吗?为什么不使用这样的if语句:
def toXml(value1:String,value2:Option[String]) =
<body>
<tag1>{value1}</tag1>
{if (value2 isDefined) <tag2>{value2.get}</tag2>}
</body>
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
}
}
}
def-toXml(value1:String,value2:Option[String])=
{value1}
{如果(value2已定义){value2.get}
这应该可以做到,并且是可以理解的,对吗?您想要的
?
功能可以像这样实现:
def toXml(value1:String,value2:Option[String]) =
<body>
<tag1>{value1}</tag1>
{if (value2 isDefined) <tag2>{value2.get}</tag2>}
</body>
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
}
}
}
为简单起见,这仅适用于单子节点,以向您展示该概念(我想您应该能够从中编写更通用的函数,以备需要)
如果隐式函数在作用域中,则可以使用?
运算符:
<body>
{ <tag1>{ Some("Hello") }</tag1>? }
{ <tag2>{ None }</tag2>? }
{ <tag3>{ Some(<innerTag/>) }</tag3>? }
{ <tag4><innerTag/></tag4>? }
{ <tag5>{ None }</tag5>? }
</body>
{{Some(“Hello”)}?}
{{None}?}
{{Some()}?}
{ ? }
{{None}?}
将导致:
<body>
<tag1>Hello</tag1>
<tag3><innerTag></innerTag></tag3>
<tag4><innerTag></innerTag></tag4>
</body>
你好
您还可以折叠
选项:
{ value2.fold(NodeSeq.Empty)(x => <tag2>{x}</tag2>) }
{value2.fold(NodeSeq.Empty)(x=>{x}}
这里有一个简单的版本,它不使用折叠方法(可以说是误导性的,因为没有积累任何东西):
value2.map(x => <tag2>{x}</tag>).getOrElse(NodeSeq.Empty)
value2.map(x=>{x}).getOrElse(NodeSeq.Empty)
结果与佐尔坦的答案相同。感谢安妮的回答,这更清楚地表明我对地图和平面的使用。然而,我希望避免为每个选项复制和粘贴isDefined测试。我正在寻找一种解决方案,其中代码看起来几乎像XML输出。这比其他答案简单得多。有没有办法避免空行?