Groovyが提供しているテンプレートエンジン:
検証環境:
Win7 64bit JDK 1.7 64bit Groovy 1.8.9
GStringTemplateEngineでは、テンプレートテキストは "groovy.tmp.templates.GStringTemplateScript[N]"([N]にはインクリメントされる数字が入る)のclosure内で処理されます。テンプレート内で
<%= dump() %> <%= inspect() %>
すると以下のように出力されます。
↓↓"<%= dump() %>"の出力 <groovy.tmp.templates.GStringTemplateScript9$_getTemplate_closure1@73b05494 \ delegate=groovy.lang.Binding@3d80fbe2 \ owner=groovy.tmp.templates.GStringTemplateScript9@5f18d1f9 \ thisObject=groovy.tmp.templates.GStringTemplateScript9@5f18d1f9 ... ↓↓"<%= inspect() %>"の出力 groovy.tmp.templates.GStringTemplateScript9$_getTemplate_closure1@73b05494
ということで、
def binding = [ title : "...", c : { s -> ... },
とした場合、テンプレート中で
<%= c(title) %>
としても、「groovy.tmp.templates.GStringTemplateScript[N]にはc()なんてメソッドありません」とエラーになります。
これを回避するには、以下のように"call()"メソッドで明示的にclosureを呼び出します。
<%= c.call(title) %>
例:
@Grapes([ @Grab(group='org.apache.commons', module='commons-lang3', version='3.1'), ]) import org.apache.commons.lang3.* String input_s = "<hello, 'bonjour' & \"evening\">" def binding = [ title : input_s, h1 : { s -> StringEscapeUtils.escapeHtml4(s).replace("'", ''') }, h2 : { s -> s.toString().replace('&', '&').replace('<', '<') .replace('>', '>').replace('"', '"').replace("'", ''') }, ] println binding.h1(input_s) println binding.h2(input_s) def engine = new groovy.text.GStringTemplateEngine() def text = '''\ Raw Title : [<%= title %>] HTML Escaped Title(1) : [<%= h1.call(title) %>] HTML Escaped Title(2) : [<%= h2.call(title) %>] ''' def template = engine.createTemplate(text).make(binding) println template.toString()
実行結果:
<hello, 'bonjour' & "evening"> <hello, 'bonjour' & "evening"> Raw Title : [<hello, 'bonjour' & "evening">] HTML Escaped Title(1) : [<hello, 'bonjour' & "evening">] HTML Escaped Title(2) : [<hello, 'bonjour' & "evening">]
もう一つの方法は、"Object"クラスにテンプレートから使いたいメソッドをmixinしてしまう方法です。
@Grapes([ @Grab(group='org.apache.commons', module='commons-lang3', version='3.1'), ]) import org.apache.commons.lang3.* String input_s = "<hello, 'bonjour' & \"evening\">" class Helper { String h1(String s) { StringEscapeUtils.escapeHtml4(s).replace("'", ''') } String h2(String s) { s.toString().replace('&', '&').replace('<', '<') .replace('>', '>').replace('"', '"').replace("'", ''') } } Object.mixin(Helper) def binding = [ title : input_s, ] println h1(input_s) println h2(input_s) def engine = new groovy.text.GStringTemplateEngine() def text = '''\ Raw Title : [<%= title %>] HTML Escaped Title(1) : [<%= h1(title) %>] HTML Escaped Title(2) : [<%= h2(title) %>] ''' def template = engine.createTemplate(text).make(binding) println template.toString()
実行結果:
<hello, 'bonjour' & "evening"> <hello, 'bonjour' & "evening"> Raw Title : [<hello, 'bonjour' & "evening">] HTML Escaped Title(1) : [<hello, 'bonjour' & "evening">] HTML Escaped Title(2) : [<hello, 'bonjour' & "evening">]