我有一个包含一些属性的 Map,我想创建一个具有这些属性的 xml 元素。
例如config是scala Map,我想如下使用它,但实际上以下不起作用。谁能帮助我?谢谢
<input type="text" {config.map(entry => entry._1 + "=" + entry._2)}></input>
可惜你写不出你想要的东西。我猜 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
将接受 aString
作为属性值。
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
.
使用低级 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
)