2011-09-05 72 views
3

我正在使用Scala播放框架。對於我的大部分頁面,我都嚴格保持HTML的視圖模板。儘管如此,我希望能夠通過一些在控制器中以編程方式生成的XML。我有以下的瑣碎的模板:在scala播放模板中使用scala.xml.Node

@(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) 

顯然我做的東西要麼是愚笨的或不允許的。有人願意讓我擺脫我的痛苦嗎?

回答

2

好的。我閱讀了資料,並找出了一個解決方法。斯卡拉發揮的模板引擎似乎讓模板內部渲染(從播放斯卡拉/ src目錄/播放/模板/ ScalaTemplate.scala exceprt)中定義的一組不同類型的,不包括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)} 
}