我正在使用Scala play框架。对于我的大多数页面,我将HTML严格保留在视图模板中。特别是对于一个页面,我希望能够通过我在控制器中以编程方式生成的一些XML。我有以下简单的模板:
@(session:play.mvc.Scope.Session, flash:play.mvc.Scope.Flash, analysisTable : scala.xml.Node )
@main(title="Home", session=session, flash=flash) {
<h1>Some title</h1>
@{analysisTable}
}
当我通过一些预先生成的XML时,我希望嵌入并导航到相应的页面,我得到:
Execution exception
InvocationTargetException occured : null
在页面上,看起来像控制台上的堆栈溢出(摘录如下):
at play.templates.BaseScalaTemplate._display_(ScalaTemplate.scala:618)
at play.templates.BaseScalaTemplate$$anonfun$_display_$1.apply(ScalaTemplate.scala:618)
at play.templates.BaseScalaTemplate$$anonfun$_display_$1.apply(ScalaTemplate.scala:618)
at scala.xml.NodeSeq.foreach(NodeSeq.scala:43)
at scala.xml.NodeSeq.foldLeft(NodeSeq.scala:43)
at play.templates.BaseScalaTemplate._display_(ScalaTemplate.scala:618)
at play.templates.BaseScalaTemplate$$anonfun$_display_$1.apply(ScalaTemplate.scala:618)
at play.templates.BaseScalaTemplate$$anonfun$_display_$1.apply(ScalaTemplate.scala:618)
at scala.xml.NodeSeq.foreach(NodeSeq.scala:43)
at scala.xml.NodeSeq.foldLeft(NodeSeq.scala:43)
at play.templates.BaseScalaTemplate._display_(ScalaTemplate.scala:618)
at play.templates.BaseScalaTemplate$$anonfun$_display_$1.apply(ScalaTemplate.scala:618)
at play.templates.BaseScalaTemplate$$anonfun$_display_$1.apply(ScalaTemplate.scala:618)
at scala.xml.NodeSeq.foreach(NodeSeq.scala:43)
at scala.xml.NodeSeq.foldLeft(NodeSeq.scala:43)
at play.templates.BaseScalaTemplate._display_(ScalaTemplate.scala:618)
at play.templates.BaseScalaTemplate$$anonfun$_display_$1.apply(ScalaTemplate.scala:618)
at play.templates.BaseScalaTemplate$$anonfun$_display_$1.apply(ScalaTemplate.scala:618)
at scala.xml.NodeSeq.foreach(NodeSeq.scala:43)
at scala.xml.NodeSeq.foldLeft(NodeSeq.scala:43)
显然,我做的事情是愚蠢的或不允许的。有人会关心让我摆脱困境吗?
答案 0 :(得分:2)
行。我阅读了这些消息来源并找到了解决办法。 scala play模板引擎似乎允许在模板中为内部呈现提供一组定义的不同类型(除了play-scala / src / play / templates / ScalaTemplate.scala),不包括scala.xml.Node:
case class BaseScalaTemplate[T<:Appendable[T],F<:Format[T]](format: F) {
def _display_(o:Any):T = {
o match {
case escaped:T => escaped
case () => format.raw("")
case None => format.raw("")
case Some(v) => _display_(v)
case escapeds:Seq[Any] => escapeds.foldLeft(format.raw(""))(_ + _display_(_))
case string:String => format.escape(string)
case v if v != null => _display_(v.toString)
case _ => format.raw("")
}
}
}
大多数人会输入字符串,但还有一些其他类型被接受。查看上面匹配语句的第一行,允许任何属于Appendable的子类型。它恰好发生了更进一步的定义:
case class Html(text:String) extends Appendable[Html] {
val buffer = new StringBuilder(text)
def +(other:Html) = {
buffer.append(other.buffer)
this
}
override def toString = buffer.toString
}
我的解决方案是将原始xml子树转换为字符串,然后将其包装在Html类中,如下所示:
@(session:play.mvc.Scope.Session, flash:play.mvc.Scope.Flash, analysisTable : scala.xml.Node )
@main(title="Home", session=session, flash=flash) {
<h1>Some title</h1>
@{new play.templates.Html(analysisTable.toString)}
}