假设我的xml文件包含如下内容:
<example name={name}/>
是否可以从Scala加载此文件并将{name}替换为作用域中名称的值?
类似于XML.loadFile,但它以与Scala的XML文字相同的方式进行数据绑定。
请注意,更复杂的示例也应该有用,例如
<example name={name}>
{for (hobby <- hobbies) yield <hobby>{hobby}</hobby>}
</example>
答案 0 :(得分:3)
这会足够吗?
import scala.collection.mutable
import scala.util.matching.Regex.Groups
import scala.xml.XML
type Data = mutable.Map[Symbol, Any]
object Data {
def empty = mutable.Map.empty[Symbol, Any]
}
class Assignment(identifier: Symbol, data: Data) {
def :=(value: Any) {
data(identifier) = value
}
}
implicit def symbol2assignment(id: Symbol)(implicit data: Data) =
new Assignment(id, data)
def bind(template: String)(implicit data: Data) = {
val attributes = """=\{([^{}]+)}""".r
.replaceAllIn((_: String), _ match {
case Groups(identifier) =>
"=\"%s\"".format(data(Symbol(identifier)))
})
val rest = """\{([^{}]+)}""".r
.replaceAllIn((_: String), _ match {
case Groups(identifier) =>
data(Symbol(identifier)).toString
})
(attributes andThen rest andThen XML.loadString)(template)
}
implicit val data = Data.empty
'name := "bob"
'text := "hi there"
val bound = bind("<ex name={name}>{text}</ex>")
assert(bound == <ex name="bob">hi there</ex>)
答案 1 :(得分:1)
object XmlBinder {
// "twitter" at "http://maven.twttr.com"
// "com.twitter" %% "util-eval" % "3.0.0"
import com.twitter.util.Eval
import scala.xml.Elem
private val template =
"""|<example name={name}>
| {for (hobby <- hobbies) yield <hobby>{hobby}</hobby>}
|</example>""".stripMargin
val name = "name"
val hobbies = List("hobby 1", "hobby 2")
def bind(): Elem = new Eval()("import XmlBinder._\n" + template)
}