witrix平臺中的tpl模板技術是一種通用的xml動態標簽技術,不僅可以用于文本生成,而且可以用于任何需要動態標簽的地方,例如工作流引擎 的配置和執行腳本。tpl模板引擎采用的不是jsp tag的標準機制,而是重新設計并實現的。在開發的后期,因為jstl標準出現,我們對標簽的命名作了一定的修改,以盡量符合標準的調用接口。tpl模板 語言完全符合xml規范,其標簽定義都是完全獨立開發的。在開發tpl的時候,我們甚至沒有看到任何類似于c:forEach和c:if的標簽設計。但是 我們發現,tpl的動態處理功能與jstl雖然命名不同,但是基本是等價的,所以修改是非常直接的過程。
FreeMarker是一種流 行的文本模板語言,其語法類似于xml tag,但是命名規則不同。這實在是一種令人費解的設計。有意思的是,我們發現tpl的功能集也包含了FreeMarker的功能集。這實際上表明了一件 事情,xml動態標簽存在一些必然的功能需求,無論是jsp tag, FreeMarker還是tpl, 所不同的只是表現形式而已。但這種表現形式的差異卻又造成了實際功能上的巨大差異。
tpl與FreeMarker具體對比如下。
宏定義
<#macro greet person>
<font size="+2">Hello ${person}</font>
</#macro>]]>
<c:lib namespace="test">
<greet demandArgs="person">
<font size="+2">Hello ${person}</font>
</greet>
</c:lib>
tpl具有更加強大的變量域控制手段,可以通過importVars參數來指定是否使用調用環境中的變量作為缺省參數。另一方面,tpl具有更加靈活的參數校驗規則,可以通過demandArgs, otherArgs等參數來指定對自定義標簽參數的校驗規則。
調用宏
<@greet person="Fred" />
<test:greet person="Fred" />
嵌套內容
<#macro border>
<table border="4" cellspacing="0" cellpadding="4"><tr><td>
<#nested>
<#nested>
</tr></td></table>
</#macro>
<c:lib namespace="test">
<border type="bodyTag">
<table border="4" cellspacing="0" cellpadding="4"><tr><td>
<cp:compile src="${tagBody}" />
</tr></td></table>
</border>
</c:lib>
tpl的<cp:compile>指令在執行時可以指定xslt參數,從而在編譯tagBody之前應用xslt變換。
復雜嵌套
與FreeMark一樣,嵌套內容可以是復雜內容
<@border>
<ul>
<@do_thrice>
<li><@greet person="Joe"/>
</@do_thrice>
</ul>
</@border>
<test:border>
<ul>
<test:do_thrice>
<li><test:greet person="Joe" /></li>
</test:do_thrice>
</ul>
</test:border>
導入庫
<#import "/lib/my_test.ftl" as my>
<c:lib src="/lib/my_test.ftl" namespace="my" />
創建或替代變量
<#assign mail="jsmith@other.com" />
<c:set var="mail" value="jsmith@other.com" default="xx"/>
判斷
<#if animals.python.price < animals.elephant.price>
Pythons are cheaper than elephants today.
</#if>
<c:if test="${lt(animals.python.price,animals.elephant.price)}">
Pythons are cheaper than elephants today.
</c:if>
tpl因為是xml語法,算術操作符<和>必須轉義后才能使用,使用起來很不方便,因而最終決定tpl不支持操作符,通過lt(), gt()等函數來實現功能。
循環
<#list animals as being>
<tr><td>${being.name}<td>${being.price} Euros
</#list>
<c:forEach var="being" items="${animals}" >
<tr><td>${being.name}<td>${being.price} Euros
</c:forEach>
tpl提供<c:tile>等多種循環方式
include指令
<#include "/copyright_footer.html">
<c:include src="/copyright_footer.html" />
tpl強大的模板功能加上jsplet框架面向對象的能力,使得我們可以輕易的封裝復雜的界面組件。而且這種封裝能力還不需要Tapestry那種復雜的配置文件。tpl對portal應用的支持也是一個自然的發展過程。