我有一个包含一些属性的Map,我想创建一个具有这些属性的xml元素。
e.g。 config是scala Map,我想将它用作以下内容,但实际上以下内容不起作用。谁能帮助我?感谢
<input type="text" {config.map(entry => entry._1 + "=" + entry._2)}></input>
答案 0 :(得分:1)
使用低级API。这是scalac解析器在解除你的xml文字时生成的内容:
import scala.xml.{UnprefixedAttribute, MetaData, TopScope, Text, Elem, Null}
val config: Map[String, String] = Map("k1" -> "v2", "k2" -> "v2")
val seed: MetaData = Null // Don't ask.
val meta: MetaData = config.toList.foldLeft(seed) {
case (acc, (s1, s2)) =>
new UnprefixedAttribute(
key = s1,
value = s2,
next = acc
)
}
Elem(
prefix = null,
label = "input",
attributes = meta,
scope = TopScope,
minimizeEmpty = false
)
答案 1 :(得分:1)
Bummer你无法写出你想要的东西。我猜Scala编译器的XML文字解析器不够复杂,只能用在任何地方插入的表达式来解析XML文字。它们只能位于标签之间或作为单独的属性值。
作为一种解决方法,可以创建没有属性的元素,或只创建一个属性,其余属性丢失:
val elem = <input type="text"/>
然后,您可以使用几个复制构造函数添加Map
中的属性。
elem.copy(
attributes = elem.attributes.copy(
config.foldLeft(scala.xml.Null: scala.xml.MetaData) {
case (next, (k, v)) => scala.xml.Attribute(k, scala.xml.Text(v), next)
}
))
res1: scala.xml.Elem = <input type="text" k2="v2" k1="v2"/>
以上使用Elem
的复制构造函数,然后使用attributes
的复制构造函数。
还可以选择只使用一个复制构造函数并稍微折叠一下:
elem.copy(attributes = config.foldRight(elem.attributes) {
case ((k, v), next) => scala.xml.Attribute(k, scala.xml.Text(v), next)
})
res2: scala.xml.Elem = <input k1="v2" k2="v2" type="text"/>
这可能是最简单的选择。
虽然,Olivier的解决方案确实显示UnprefixedAttributed
会接受String
作为属性值。
elem.copy(attributes = config.foldRight(elem.attributes) {
case ((k, v), next) => new scala.xml.UnprefixedAttribute(k, v, next)
})
res3: scala.xml.Elem = <input k1="v2" k2="v2" type="text"/>
这样可以避免必须生成Text
元素,以便为NodeSeq
提供Attribute
值。