stringTemplate是一个模板引擎,同时支持java,C#,Python.
StringTemplate 语法说明
StringTemplate的语法是以$xxxx$来进行分割的. stringtemplate关键写是区分大小写的.powered by 25175.net
属性引用
名称属性
在模板中,这个是最常用的一个属性.用于显示文字.如下:
你的邮件地址:$email$
替换属性名为email的值.
同一个属性可以有多个值,多个值的语法如下
$value;null="xxx",separator=", "$
定义value属性,当value为null则显示xxx.如果有多个属性值则以,号分开
字段引用
如果一个属性名称是对象或集合.可以用 属性名称.字段名 访问字段值
例如:
你的姓名: $人.姓名$
你的邮件:$人.邮件$
使用语法: $对象名.字段名$
在C#可以直接将一个对象设置到一个属性名称中.
如:
User us = new User();
us.Name = "xxsssx";
us.Value ="80";
StringTemplate st = new StringTemplate("$User.Name$,$User.Value$");
st.SetAttribute("User", us);
Console.WriteLine(st.ToString());
对于键/值对象,也同样使用上面方式进行访问如:
StringTemplate a = new StringTemplate("$user.name$, $user.phone$");
Hashtable user = new Hashtable();
user.Add("name", "Terence");
user.Add("phone", "none-of-your-business");
a.SetAttribute("user", user);
string results = a.ToString();
自定义属性字段名
格式: $属性名:{it.字段名}$
例如:
StringTemplate st = new StringTemplate("$abcdef:{第一个: $it.ddddd$ 第二个:$it.ddddd$}$");
st.SetAttribute("abcdef.{ddddd,ddddd}","中国人", "我不来了");
Console.WriteLine(st.ToString());
如果字段名是保留字,可以使用$对象名.("保留字")$
一次显示多个属性
$[属性名,属性名]$
模板引用
必需把模板加入同一个模板组,才能相互之间调用模板.
通过$模板名()$来调用模板
模板传参数
$模板名(参数名=参数值,参数名=参数值)$
例如:
StringTemplateGroup Group = new StringTemplateGroup("Temp");
Group.Definetemplate("link", "<a href='$url$'>$title$</a>");
StringTemplate st = new StringTemplate(Group, "调用link模板,显示链接 $link(url=\"/faq/view?ID=\"+faqid, title=faqtitle)$ ,真的啊!");
st.SetAttribute("faqid", 1);
st.SetAttribute("title","中华人民共和国");
Console.WriteLine(st.ToString());
循环显示使用
User us = new User();
us.Name = "哈哈";
us.Value = "99";
List<User> uss = new List<User>();
uss.Add(us);
uss.Add(us);
uss.Add(us);
uss.Add(us);
StringTemplate st = new StringTemplate("<table>$User:{<tr>$it.Name$<td></td>$it.Value$</tr>}$</table>");
st.SetAttribute("User", uss);
Console.WriteLine(st.ToString());
通过模板交替显示
StringTemplateGroup group = new StringTemplateGroup("Test");
group.Definetemplate("TrRed", "<tr class=red><td>$it.name$</td><td>$it.value$</td></tr>\n");
group.Definetemplate("TrWither", "<tr class=wither><td>$it.name$</td><td>$it.value$</td></tr>\n");
StringTemplate st = new StringTemplate(group, "<table>$User:TrRed(),TrWither()$</table>");
User us = new User();
us.Name = "哈哈哈";
us.Value = "999";
List<User> uss = new List<User>();
uss.Add(us);
uss.Add(us);
uss.Add(us);
st.SetAttribute("User", uss);
Console.WriteLine(st.ToString());
例子教程下载:下载
附:英文语法介绍
Syntax |
Description |
<attribute> |
Evaluates to the value of attribute.ToString() if it exists else empty string. |
<i>, <i0> |
The iteration number indexed from one and from zero, respectively, when referenced within a template being applied to an attribute or attributes. |
<attribute.property> |
Looks for property of attribute as a property (C#), then accessor methods like getProperty()or isProperty(). If that fails, StringTemplate looks for a raw field of the attribute calledproperty. Evaluates to the empty string if no such property is found. |
<attribute.(expr)> |
Indirect property lookup. Same as attribute.property except use the value of expr as the property_ name. Evaluates to the empty string if no such property is found. |
<multi-valued-attribute> |
Concatenation of ToString() invoked on each element. If multi-valued-attribute is missing his evaluates to the empty string. |
<multi-valued-attribute; separator=expr> |
Concatenation of ToString() invoked on each element separated by expr. |
<template(argument-list)> |
Include template. The argument-list is a list of attribute assignments where each assignment is of the form arg-of-template=expr where expr is evaluated in the context of the surrounding template |
<(expr)(argument-list)> |
Include template whose name is computed via expr. The argument-list is a list of attribute assignments where each assignment is of the form attribute=expr. Example $(whichFormat)()$ looks up whichFormat's value and uses that as template name. Can also apply an indirect template to an attribute. |
<attribute:template(argument-list)> |
Apply template to attribute. The optional argument-list is evaluated before application so that you can set attributes referenced within template. The default attribute it is set to the value of attribute. If attribute is multi-valued, then it is set to each element in turn and template is invoked n times where n is the number of values in attribute. Example: $name:bold() appliesbold() to name's value. |
<attribute:(expr)(argument-list)> |
Apply a template, whose name is computed from expr, to each value of attribute. Example$data:(name)()$ looks up name's value and uses that as template name to apply to data. |
<attribute:t1(argument-list): ... :tN(argument-list)> |
Apply multiple templates in order from left to right. The result of a template application upon a multi-valued attribute is another multi-valued attribute. The overall expression evaluates to the concatenation of all elements of the final multi-valued attribute resulting from templateN'sapplication. |
<attribute:{anonymous-template}> |
Apply an anonymous template to each element of attribute. The iterated it atribute is set automatically. |
<attribute:{argument-name_ | _anonymous-template}> |
Apply an anonymous template to each element of attribute. Set the argument-name to the iterated value and also set it. |
<a1,a2,...,aN:{argument-list_ | _anonymous-template}> |
Parallel list iteration. March through the values of the attributes a1..aN, setting the values to the arguments in argument-list in the same order. Apply the anonymous template. There is no defined it value unless inherited from an enclosing scope. |
<attribute:t1(),t2(),...,tN()> |
Apply an alternating list of templates to the elements of attribute. The template names may include argument lists. |
<if(attribute)>subtemplate |
If attribute has a value or is a bool object that evaluates to true, include subtemplate else include subtemplate2. These conditionals may be nested. |
<if(!attribute)>subtemplate<endif> |
If attribute has no value or is a bool object that evaluates to false, include subtemplate. These conditionals may be nested. |
<first(attr)> |
The first or only element of attr. You can combine operations to say things likefirst(rest(names)) to get second element. |
<last(attr)> |
The last or only element of attr. |
<rest(attr)> |
All but the first element of attr. Returns nothing if $attr$ a single valued. |
<strip(attr)> |
Returns an iterator that skips any null values in $attr$. strip |
<length(attr)> |
Return an integer indicating how many elements in length $attr$ is. Single valued attributes return 1. Strings are not special; i.e., length("foo") is 1 meaning "1 attribute". Nulls are counted in lists so a list of 300 nulls is length 300. If you don't want to count nulls, uselength(strip(list)). |
\$ or \< |
escaped delimiter prevents $ or < from starting an attribute expression and results in that single character. |
<\ >, <\n>, <\t>, <\r> |
special characters: space, newline, tab, carriage return. |
<! comment !>, $! comment !$ |
1 变量替换
public static void fun1() {
StringTemplate st = new StringTemplate(
"对象变量替换 姓名:$KeyList.Name$, 年龄:$KeyList.Age$ ");
HashMap ht = new HashMap();
ht.put("Name", "李四");
ht.put("Age", "35");
st.setAttribute("KeyList", ht);
System.out.print(st.toString());
}
2 自定义集合替换
public static void fun2() {
StringTemplate st = new StringTemplate(
"自定义集合替换 $List:{姓名:$it.Name$ 年龄:$it.Age$}$");
st.setAttribute("List.{Name,Age}", "王二", "29");
System.out.print(st.toString());
}
3 对象变量替换
定义类
private static class User {
String name;
String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
public static void fun3() {
User us = new User();
us.name = "张三";
us.age = "23";
List<User> uss = new ArrayList<User>();
uss.add(us);
uss.add(us);
uss.add(us);
uss.add(us);
uss.add(us);
StringTemplate st = new StringTemplate(
"<table>$Item:{<tr class=black><td>$it.name$</td></tr>},{<tr class=red><td>$it.age$</td></tr>};separator=\"\n\"$</table>");
st.setAttribute("Item", uss);
System.out.print(st.toString());
}
交叉替换
public static void fun4() {
User us = new User();
us.name = "张三";
us.age = "23";
List<User> uss = new ArrayList<User>();
uss.add(us);
uss.add(us);
uss.add(us);
uss.add(us);
uss.add(us);
StringTemplateGroup sg = new StringTemplateGroup("GroupTest");
sg.definetemplate("RowRed",
"<tr class=red><td>$it.Name$</td><td>$it.Age$</td></tr>\n");
sg.definetemplate("Rowblack",
"<tr class=black><td>$it.Name$</td><td>$it.Age$</td></tr>\n");
StringTemplate st = sg.definetemplate("List",
"<table>$Item:RowRed(),Rowblack()$</table>");
st.setAttribute("Item", uss);
System.out.print(st.toString());
}
4 条件判断
public static void fun5() {
StringTemplate st = new StringTemplate(
"当前用户登陆状态: $if(IsAdmin)$ 用户登陆成功! $else$ 用户没有登陆! $endif$");
st.setAttribute("IsAdmin", true);
System.out.print(st.toString());
}
5 sql语句实现
theQuery.st内容
SELECT $column; separator=","$ FROM $table$;
public static void fun6() {
// 一个sql语句的实现
StringTemplateGroup group = new StringTemplateGroup("myGroup", "c:/");
StringTemplate query = group.getInstanceOf("theQuery");
query.setAttribute("column", "name");
query.setAttribute("column", "email");
query.setAttribute("table", "User");
System.out.print(query.toString());
}
6 使用AttributeRenderer
private static class DateRenderer implements AttributeRenderer {
public String toString(Object o) {
SimpleDateFormat f = new SimpleDateFormat("yyyy.MM.dd");
return f.format(((Calendar) o).getTime());
}
}
public static void fun7() {
StringTemplate st = new StringTemplate("date: <created>",
AngleBracketTemplateLexer.class);
st.setAttribute("created", new GregorianCalendar(2005, 07 - 1, 05));
st.registerRenderer(GregorianCalendar.class, new DateRenderer());
String result = st.toString();
System.out.print(result.toString());
}
==========================
示例2
==========================
using System;
using System.Collections.Generic;
using System.Text;
using Antlr.StringTemplate;
using Antlr.StringTemplate.Language;
using System.IO;
using System.Collections;
using System.Collections.Specialized;
namespace TemplateExplame
{
class Program
{
static void Main(string[] args)
{
//简单变量替换();
//复杂变量替换();
//对象变量替换();
//键值类型替换();
//自定义集合替换();
//同时显示多个变量();
//模板调用();
//给调用模板传参数();
//值模板();
//简单循环();
//交差循环显示();
//通过模板交差循环();
//条件判断();
//从文件中创建模板();
}
#region "变量处理"
private static void 简单变量替换()
{
StringTemplate st = new StringTemplate("简单变量替换 $Text$,真的啊!");
st.SetAttribute("Text", "中华人民共和国");
Console.WriteLine(st.ToString());
}
private static void 复杂变量替换()
{
StringTemplate st = new StringTemplate("复杂变量替换 $Text;null=\"为空值\",separator=\",\"$ 真是复杂啊!");
st.SetAttribute("Text", "中国",null,"台湾","印度");
Console.WriteLine(st.ToString());
}
/// <summary>
/// 如果对象的字段名中有保留字,请用对象名.("变量名")来进行访问.
/// </summary>
private static void 对象变量替换()
{
StringTemplate st = new StringTemplate("对象变量替换 姓名:$User.Name$, 年龄:$User.Age$ ");
User us = new User();
us.Name = "张三";
us.Age = "30";
st.SetAttribute("User", us);
Console.WriteLine(st.ToString());
}
private static void 键值类型替换()
{
StringTemplate st = new StringTemplate("对象变量替换 姓名:$KeyList.Name$, 年龄:$KeyList.Age$ ");
Hashtable ht = new Hashtable();
ht.Add("Name", "李四");
ht.Add("Age", "35");
st.SetAttribute("KeyList", ht);
Console.WriteLine(st.ToString());
}
private static void 自定义集合替换()
{
StringTemplate st = new StringTemplate("自定义集合替换 $List:{姓名:$it.Name$ 年龄:$it.Age$}$");
st.SetAttribute("List.{Name,Age}", "王二", "29");
Console.WriteLine(st.ToString());
}
private static void 同时显示多个变量()
{
StringTemplate st = new StringTemplate("变量相加 $[Temp1,Temp2,Temp3]$");
//StringTemplate st = new StringTemplate("变量相加 $[Temp1,Temp2,Temp3];separator=\",\"$");
st.SetAttribute("Temp1", "变量1");
st.SetAttribute("Temp2", "变量2");
st.SetAttribute("Temp3", "变量3");
Console.WriteLine(st.ToString());
}
#endregion
#region "模板应用"
/// <summary>
/// 模板要相互调用,必需将要调用的模板放入同一个模板组里,才能相互调用.
/// </summary>
private static void 模板调用()
{
StringTemplateGroup sg = new StringTemplateGroup("GroupTest");
sg.Definetemplate("Box", "中华人民共和国中华人民共和国,中华人民共和国");
StringTemplate st = sg.Definetemplate("List", "下面是我调用Box模板内容:\n$Box()$");
Console.WriteLine(st.ToString());
}
/// <summary>
/// 参数可以为值,变量,模板
/// </summary>
private static void 给调用模板传参数()
{
StringTemplateGroup sg = new StringTemplateGroup("GroupTest");
sg.Definetemplate("BoxA", "我不来了()");
sg.Definetemplate("Box", "中华人民共和国,中华全国 Title: $Title$ !!");
StringTemplate st = sg.Definetemplate("List", "下面是我调用Box模板内容:\n$Box(Title=\"标题值\")$"); //传变量值
//StringTemplate st = sg.Definetemplate("List", "下面是我调用Box模板内容:\n$Box(Title={$Titles$})$"); //传变量
//StringTemplate st = sg.Definetemplate("List", "下面是我调用Box模板内容:\n$Box(Title=BoxA())$"); //传模板
st.SetAttribute("Titles", "标题参数值");
Console.WriteLine(st.ToString());
}
private static void 值模板()
{
StringTemplateGroup sg = new StringTemplateGroup("GroupTest");
sg.Definetemplate("Box", "中华人民共和国,,,,");
StringTemplate st = new StringTemplate(sg, "调用值模板$Mys:Box();separator=\"==\"$------s");
st.SetAttribute("Mys", "中国");
st.SetAttribute("Mys", "中国");
Console.WriteLine(st.ToString());
}
#endregion
#region "循环显示"
private static void 简单循环()
{
StringTemplate st = new StringTemplate("<table>$Item:{<tr><td>$it$要循环显示的内容</td></tr>}$</table>");
for (int i = 0; i < 10; i++)
{
st.SetAttribute("Item", i);
}
Console.WriteLine(st.ToString());
}
private static void 交差循环显示()
{
User us = new User();
us.Name = "张三";
us.Age = "23";
List<User> uss = new List<User>();
uss.Add(us);
uss.Add(us);
uss.Add(us);
uss.Add(us);
uss.Add(us);
StringTemplate st = new StringTemplate("<table>$Item:{<tr class=black><td>$it.Name$</td></tr>},{<tr class=red><td>$it.Age$</td></tr>};separator=\"\n\"$</table>");
st.SetAttribute("Item", uss);
Console.WriteLine(st.ToString());
}
private static void 通过模板交差循环()
{
User us = new User();
us.Name = "张三";
us.Age = "23";
List<User> uss = new List<User>();
uss.Add(us);
uss.Add(us);
uss.Add(us);
uss.Add(us);
uss.Add(us);
StringTemplateGroup sg = new StringTemplateGroup("GroupTest");
sg.Definetemplate("RowRed", "<tr class=red><td>$it.Name$</td><td>$it.Age$</td></tr>\n");
sg.Definetemplate("Rowblack", "<tr class=black><td>$it.Name$</td><td>$it.Age$</td></tr>\n");
StringTemplate st = sg.Definetemplate("List", "<table>$Item:RowRed(),Rowblack()$</table>");
st.SetAttribute("Item", uss);
Console.WriteLine(st.ToString());
}
#endregion
#region "条件判断"
private static void 条件判断()
{
StringTemplate st = new StringTemplate("当前用户登陆状态: $if(IsAdmin)$ 用户登陆成功! $else$ 用户没有登陆! $endif$");
st.SetAttribute("IsAdmin", true);
Console.WriteLine(st.ToString());
}
#endregion
private static void 从文件中创建模板()
{
StringTemplateGroup group = new StringTemplateGroup("myGroup", new LoadFileHtm(AppDomain.CurrentDomain.BaseDirectory+@"Template\") , typeof(DefaultTemplateLexer));
StringTemplate helloAgain = group.GetInstanceOf("homepage");
helloAgain.SetAttribute("title", "Welcome To StringTemplate");
helloAgain.SetAttribute("name", "World");
helloAgain.SetAttribute("friends", "Terence");
helloAgain.SetAttribute("friends", "Kunle");
helloAgain.SetAttribute("friends", "Micheal");
helloAgain.SetAttribute("friends", "Marq");
Console.WriteLine(helloAgain.ToString());
}
}
public class LoadFileHtm : StringTemplateLoader
{
/// <summary>
/// How are the files encoded (ascii, UTF8, ...)? You might want to read
/// UTF8 for example on a ascii machine.
/// </summary>
private Encoding encoding;
private FileSystemWatcher filesWatcher;
private HybridDictionary fileSet;
public LoadFileHtm()
: this(null, Encoding.Default, true)
{
}
public LoadFileHtm(string locationRoot)
: this(locationRoot, Encoding.Default, true)
{
}
public LoadFileHtm(string locationRoot, bool raiseExceptionForEmptyTemplate)
: this(locationRoot, Encoding.Default, raiseExceptionForEmptyTemplate)
{
}
public LoadFileHtm(string locationRoot, Encoding encoding)
: this(locationRoot, encoding, true)
{
}
public LoadFileHtm(string locationRoot, Encoding encoding, bool raiseExceptionForEmptyTemplate)
: base(locationRoot, raiseExceptionForEmptyTemplate)
{
if ((locationRoot == null) || (locationRoot.Trim().Length == 0))
{
this.locationRoot = AppDomain.CurrentDomain.BaseDirectory;
}
this.encoding = encoding;
fileSet = new HybridDictionary(true);
}
/// <summary>
/// Determines if the specified template has changed.
/// </summary>
/// <param name="templateName">template name</param>
/// <returns>True if the named template has changed</returns>
public override bool HasChanged(string templateName)
{
//string templateLocation = Path.Combine(LocationRoot, GetLocationFromTemplateName(templateName));
string templateLocation = string.Format("{0}/{1}", LocationRoot, GetLocationFromTemplateName(templateName)).Replace('\\', '/');
object o = fileSet[templateLocation];
if ((o != null))
{
return true;
}
return false;
}
/// <summary>
/// Loads the contents of the named StringTemplate.
/// </summary>
/// <param name="templateName">Name of the StringTemplate to load</param>
/// <returns>
/// The contexts of the named StringTemplate or null if the template wasn't found
/// </returns>
/// <exception cref="TemplateLoadException">Thrown if error prevents successful template load</exception>
protected override string InternalLoadTemplateContents(string templateName)
{
string templateText = null;
string templateLocation = null;
try
{
//templateLocation = Path.Combine(LocationRoot, GetLocationFromTemplateName(templateName));
templateLocation = string.Format("{0}/{1}", LocationRoot, GetLocationFromTemplateName(templateName)).Replace('\\', '/');
StreamReader br;
try
{
br = new StreamReader(templateLocation, encoding);
}
catch (FileNotFoundException)
{
return null;
}
catch (DirectoryNotFoundException)
{
return null;
}
catch (Exception ex)
{
throw new TemplateLoadException("Cannot open template file: " + templateLocation, ex);
}
try
{
templateText = br.ReadToEnd();
if ((templateText != null) && (templateText.Length > 0))
{
//templateText = templateText.Trim();
if (filesWatcher == null)
{
filesWatcher = new FileSystemWatcher(LocationRoot, "*.htm");
//filesWatcher.InternalBufferSize *= 2;
filesWatcher.NotifyFilter =
NotifyFilters.LastWrite
| NotifyFilters.Attributes
| NotifyFilters.Security
| NotifyFilters.Size
| NotifyFilters.CreationTime
| NotifyFilters.DirectoryName
| NotifyFilters.FileName;
filesWatcher.IncludeSubdirectories = true;
filesWatcher.Changed += new FileSystemEventHandler(OnChanged);
filesWatcher.Deleted += new FileSystemEventHandler(OnChanged);
filesWatcher.Created += new FileSystemEventHandler(OnChanged);
filesWatcher.Renamed += new RenamedEventHandler(OnRenamed);
filesWatcher.EnableRaisingEvents = true;
}
}
fileSet.Remove(templateLocation);
}
finally
{
if (br != null) ((IDisposable)br).Dispose();
br = null;
}
}
catch (ArgumentException ex)
{
string message;
if (templateText == null)
message = string.Format("Invalid file character encoding: {0}", encoding);
else
message = string.Format("The location root '{0}' and/or the template name '{1}' is invalid.", LocationRoot, templateName);
throw new TemplateLoadException(message, ex);
}
catch (IOException ex)
{
throw new TemplateLoadException("Cannot close template file: " + templateLocation, ex);
}
return templateText;
}
/// <summary>
/// Returns the location that corresponds to the specified template name.
/// </summary>
/// <param name="templateName">template name</param>
/// <returns>The corresponding template location or null</returns>
public override string GetLocationFromTemplateName(string templateName)
{
return templateName + ".htm";
}
/// <summary>
/// Returns the template name that corresponds to the specified location.
/// </summary>
/// <param name="templateName">template location</param>
/// <returns>The corresponding template name or null</returns>
public override string GetTemplateNameFromLocation(string location)
{
//return Path.ChangeExtension(location, string.Empty);
return Path.ChangeExtension(location, null);
}
#region FileSystemWatcher Events
private void OnChanged(object source, FileSystemEventArgs e)
{
string fullpath = e.FullPath.Replace('\\', '/');
fileSet[fullpath] = locationRoot;
}
private void OnRenamed(object source, RenamedEventArgs e)
{
string fullpath = e.FullPath.Replace('\\', '/');
fileSet[fullpath] = locationRoot;
fullpath = e.OldFullPath.Replace('\\', '/');
fileSet[fullpath] = locationRoot;
}
#endregion
}
public class Link
{
public string faqid;
public string faqtitle;
}
public class User
{
public string Name = "";
public string Age = "";
}
public static class FileHelp
{
public static string Read(string filename,string Dir)
{
filename = AppDomain.CurrentDomain.BaseDirectory + Dir + filename;
using(FileStream fs = new FileStream(filename,FileMode.Open,FileAccess.Read))
{
StreamReader sr = new StreamReader(fs,Encoding.Default);
return sr.ReadToEnd();
}
}
}
}