1

假设我有这样的内容的 xml 文件:

<example name={name}/>

是否可以从 Scala 加载此文件并将 {name} 替换为范围内的名称值?

所以像 XML.loadFile 这样的东西,但它以与 Scala 的 XML 文字相同的方式进行数据绑定。

请注意,更复杂的示例也应该起作用,例如

<example name={name}>
   {for (hobby <- hobbies) yield <hobby>{hobby}</hobby>}
</example>
4

2 回答 2

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>)
于 2012-04-17T22:44:50.293 回答
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)
}
于 2012-04-18T21:42:18.807 回答