VTL语法
注释
单行注释以##开始,多行注释以#*开始,以*#结束。注释的内容不会出现在输出中
属性
属性引用以$符号开始。属性可以是服务器端C#代码设置的,也可以在NVelocity模板中定义属性,比如下面语句在NVelocity模板中定义一个属性
#set (#msg="this variable is defined in NVelocity.")
NVelocity中定义的属性一般为字符串值,赋值时可以使用单引号将字符串值括起来,也可以使用双引号,他们的区别是:如果字符串值中有用到其他变量,使用单引号时该变量名字直接作为字符串的值处理,而使用双引号时该变量名字将使用属性的值进行替换(可以设置NVelocity关闭这个选项)
在模板中如果需要输出以$符号开始的文本(非变量),有2种处理方式。如果他不会作为属性赋值,则可以直接输出,因为NVelocity对没有赋值的属性,直接输出属性名字(包括$符号);如果他是一个已经赋值的属性,则需要在$符号前面添加一个转义用的反斜杠\符号
对于非字符串类型的属性,NVelocity调用属性的ToString()方法转换为字符串输出
对于对象类型的属性,可以使用类似$contact.Name方式,NVelocity目前的版本已经支持属性名称非大小写敏感
控制指令
条件指令:
NVelocity中的控制指令基本上就2个:条件指令和循环指令。NVelocity对宏的支持不太好
#if($score>1000) Expert #elseif($score>500) Senior #else Junior #endif
与Velocity不一样的地方:NVelocity不支持#{else}这个语法,#else、#endif指令必须与前后的内容空格分开
循环指令:
NVelocity的循环指令,每个指令必须单独占用一行,不能有注释、输出内容等
NVelocity对Velocity的循环指令做了扩展,加入了 Fog Creek的Fancy Loops
基本语法如下:
其他还有#include、#parse、#stop指令,详细的语法参考 VTL Reference
基本用法
下载Castle NVelocity项目,建一个测试用的web site,引用NVelocity.dll,引用的命名空间如下:
页面.cs代码如下:
则页面运行结果:
上面的代码中,演示了在NVelocity模板中调用对象的方法,比如$c.get_Name()通过getter方法读取属性值;$c.set_Name("$c.name - W")为每个contact的名字添加一个-W后缀
如果$contacts集合中没有记录,则只会输出No contacts found!文本,不会输出任何table信息,包括#beforeall、#afterall指令中的内容也不会输出
接下来测试一下#foreach指令能够支持的集合类型以及用法(只要支持IEnumarable接口的都可以使用#foreach指令)
NVelocity模板如下:
服务器端设置属性的代码如下:
页面运行效果如下:
注释
单行注释以##开始,多行注释以#*开始,以*#结束。注释的内容不会出现在输出中
属性
属性引用以$符号开始。属性可以是服务器端C#代码设置的,也可以在NVelocity模板中定义属性,比如下面语句在NVelocity模板中定义一个属性
#set (#msg="this variable is defined in NVelocity.")
NVelocity中定义的属性一般为字符串值,赋值时可以使用单引号将字符串值括起来,也可以使用双引号,他们的区别是:如果字符串值中有用到其他变量,使用单引号时该变量名字直接作为字符串的值处理,而使用双引号时该变量名字将使用属性的值进行替换(可以设置NVelocity关闭这个选项)
在模板中如果需要输出以$符号开始的文本(非变量),有2种处理方式。如果他不会作为属性赋值,则可以直接输出,因为NVelocity对没有赋值的属性,直接输出属性名字(包括$符号);如果他是一个已经赋值的属性,则需要在$符号前面添加一个转义用的反斜杠\符号
对于非字符串类型的属性,NVelocity调用属性的ToString()方法转换为字符串输出
对于对象类型的属性,可以使用类似$contact.Name方式,NVelocity目前的版本已经支持属性名称非大小写敏感
控制指令
条件指令:
NVelocity中的控制指令基本上就2个:条件指令和循环指令。NVelocity对宏的支持不太好
#if($score>1000) Expert #elseif($score>500) Senior #else Junior #endif
与Velocity不一样的地方:NVelocity不支持#{else}这个语法,#else、#endif指令必须与前后的内容空格分开
循环指令:
NVelocity的循环指令,每个指令必须单独占用一行,不能有注释、输出内容等
NVelocity对Velocity的循环指令做了扩展,加入了 Fog Creek的Fancy Loops
基本语法如下:
#foreach($i in $items)
#each
(this is optional since its the default section)
text which appears for each item
#before
text which appears before each item
#after
text which appears after each item
#between
text which appears between each two items
#odd
text which appears for every other item, including the first
#even
text which appears for every other item, starting with the second
#nodata
Content rendered if $items evaluated to null or empty
#beforeall
text which appears before the loop, only if there are items
matching condition
#afterall
text which appears after the loop, only of there are items
matching condition
#end
Fancy Loops指令非常实用,例如在StringTemplate中想要类似的效果就比较麻烦
Fancy Loops指令非常实用,例如在StringTemplate中想要类似的效果就比较麻烦
其他还有#include、#parse、#stop指令,详细的语法参考 VTL Reference
基本用法
下载Castle NVelocity项目,建一个测试用的web site,引用NVelocity.dll,引用的命名空间如下:
using System;
using System.Collections.Generic;
using System.Data;
using Commons.Collections;
using NVelocity;
using NVelocity.App;
using NVelocity.Runtime;
建立一个NVelocity模板,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
<
div
class="query-form">
<
table
>
<
tr
>
<
td
>姓名:</
td
>
<
td
><
input
type="text" id="txtQryName" class="text" value="$qryName" /></
td
>
<
td
>地址:</
td
>
<
td
><
input
type="text" id="txtQryAddress" class="text" value="$qryAddress" /></
td
>
<
td
><
input
type="button" id="btnQuery" value="查询" /></
td
>
</
tr
>
</
table
>
</
div
>
<
br
>
<
h2
>Contact List</
h2
>
<
div
class="contact-list">
#foreach($c in $contacts)
#beforeall
<
table
>
<
tr
class="list-header">
<
td
>姓名</
td
>
<
td
>邮箱</
td
>
<
td
>地址</
td
>
<
td
>会员等级</
td
>
</
tr
>
#odd
<
tr
class="list-odd">
#even
<
tr
class="list-even">
#each
<
td
>$c.set_Name("$c.name - W") $c.get_Name()</
td
>
<
td
><
a
href="mailto:$c.EMail">$c.EMail</
a
></
td
>
<
td
>$c.Address</
td
>
<
td
>#if($c.TotalOrderAmt>1000)钻卡会员
#elseif($c.TotalOrderAmt>200)金卡会员
#else Standard#end</
td
>
#after
</
tr
>
#afterall
</
table
>
#nodata
No contacts found!
#end
</
div
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
public
class
Contact
{
public
string
Name {
get
;
set
; }
public
string
EMail {
get
;
set
; }
public
string
Address {
get
;
set
; }
public
decimal
TotalOrderAmt {
get
;
set
; }
}
<br>
protected
void
Page_Load(
object
sender, EventArgs e)
{
VelocityEngine engine =
new
VelocityEngine();
ExtendedProperties prop =
new
ExtendedProperties();
prop.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, Server.MapPath(
"./"
));
prop.AddProperty(RuntimeConstants.ENCODING_DEFAULT,
"utf-8"
);
engine.Init(prop);
Template template = engine.GetTemplate(
"contact-list.vm"
);
VelocityContext context =
new
VelocityContext();
context.Put(
"contacts"
,
new
List<Contact>()
{
new
Contact() {
Name=
"Richie Liu"
, TotalOrderAmt=180,
EMail=
"RichieLiu-test@gmail.com"
,
Address=
"上海徐汇区钦州路"
},
new
Contact() {
Name=
"Kevin Zhang"
,TotalOrderAmt=0,
EMail=
"KevinZhang-test@gmail.com"
,
Address=
"苏州新区"
},
new
Contact() {
Name=
"Eric Wong"
, TotalOrderAmt=626,
EMail=
"EricWong-test@gmail.com"
,
Address=
"厦门海沧"
},
new
Contact() {
Name=
"RicCC"
, TotalOrderAmt=2080,
EMail=
"RicCC-test@gmail.com"
,
Address=
"上海徐汇区钦州路"
}
});
context.Put(
"qryName"
,
"Ric"
);
context.Put(
"qryAddress"
, DateTime.Now);
<br>
template.Merge(context,
this
.Response.Output);
}
|
![](https://i-blog.csdnimg.cn/blog_migrate/fe087505b71ba644630b740fac87f492.jpeg)
上面的代码中,演示了在NVelocity模板中调用对象的方法,比如$c.get_Name()通过getter方法读取属性值;$c.set_Name("$c.name - W")为每个contact的名字添加一个-W后缀
如果$contacts集合中没有记录,则只会输出No contacts found!文本,不会输出任何table信息,包括#beforeall、#afterall指令中的内容也不会输出
接下来测试一下#foreach指令能够支持的集合类型以及用法(只要支持IEnumarable接口的都可以使用#foreach指令)
NVelocity模板如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
<
br
/>
<
h2
>Item List - Array</
h2
>
<
div
>
#foreach($item in $items1)
#each
$item
#between
,
#end
</
div
>
<
br
>
<
br
/>
<
h2
>Item List - List</
h2
>
<
div
>
#foreach($item in $items2)
#each
$item.ToString("yyyy-MM-dd")
#between
,
#end
</
div
>
<
br
>
<
br
/>
<
h2
>Item List - Dictionary</
h2
>
<
div
>
#foreach($item in $items3)
#each
{ $item.Key - $item.Value }
#between
,#end
</
div
>
<
br
>
<
br
/>
<
h2
>Item List - DataTable</
h2
>
<
div
>
#foreach($item in $items4.Rows)
{ $item.Key - $item.Value }
#between
,
#end
</
div
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
context.Put(
"items1"
,
new
string
[] {
"AAA"
,
"BBB"
,
"CCC"
});
context.Put(
"items2"
,
new
List<DateTime> {
new
DateTime(1979, 1, 1),
new
DateTime(2010, 4, 1) });
<br>
IDictionary<
string
,
decimal
> dic =
new
Dictionary<
string
,
decimal
>();
dic.Add(
"AAA"
, 111M);
dic.Add(
"BBB"
, 222M);
dic.Add(
"CCC"
, 333M);
context.Put(
"items3"
, dic);
<br>
DataTable table =
new
DataTable();
table.Columns.Add(
new
DataColumn(
"Key"
,
typeof
(
string
)));
table.Columns.Add(
new
DataColumn(
"Value"
,
typeof
(
int
)));
DataRow row = table.NewRow();
row[
"Key"
] =
"item 1"
;
row[
"Value"
] = 111;
table.Rows.Add(row);
row = table.NewRow();
row[
"Key"
] =
"item 2"
;
row[
"Value"
] = 222;
table.Rows.Add(row);
context.Put(
"items4"
, table);
|
![](https://i-blog.csdnimg.cn/blog_migrate/40fa8c23f246a50ebc950c713b55a2ac.jpeg)