ctemplate的使用
CTemplate是一种简单但功能强大的模板引擎,它是Google制作的一个开源C++库,广泛用于各种HTML模板解析和生成。CTemplate的主要优点是简单和灵活。它将模板和逻辑分开,使得页面布局和细节(HTML)与控制流、条件等逻辑分离,使软件的维护和修改变得更容易。
使用CTemplate的基本步骤如下:
创建模板文件:模板文件是普通的文件,比如一个HTML文件。在你想插入变量的地方使用{{VARIABLE_NAME}}
的形式。
例如,在一个HTML模板中,你可以写
<h1>{{TITLE}}</h1>
<p>{{CONTENT}}</p>
在代码中填充模板:首先,你需要创建一个TemplateDictionary
的实例,并为其添加变量。
#include <ctemplate/template.h>
ctemplate::TemplateDictionary dict("example");
dict.SetValue("TITLE", "Hello, World!");
dict.SetValue("CONTENT", "Welcome to my website.");
渲染模板:最后,你可以将填充了数据的TemplateDictionary
对象和模板文件放入ExpandTemplate
函数,生成结果字符串。
std::string output;
ctemplate::ExpandTemplate("template.html", ctemplate::DO_NOT_STRIP, &dict, &output);
ExpandTemplate
函数将模板文件template.html
和已填充的dict
对象作为输入,并填充在output
字符串中。
如果你想在模板中添加复杂的控制结构,如循环或条件语句,CTemplate也提供了相关的机制。你可以在CTemplate的官方文档中找到更多关于这部分的信息。
温馨提示:在使用CTemplate时,请确保已经在你的系统中安装了这个库。如果没有,你可以通过许多包管理工具(如apt,homebrew,或编译源代码)来进行安装。
ctemplate模板中有四中标记,对应的数据字典也有不同的处理方式:
- 变量,{{变量名}},用两个大括号包含的就是变量名,在c++代码中,可以对变量赋值,任何类型的值都可以(如字符,整数,日期等)。
- 片断,{{#片断名}},片断在数据字典中表现为一个子字典,字典是可以分级的,根字典下面有多级子字典。片断可以处理条件判断和循环。
- 包含,{{>模板名}}包含指的是一个模板可以包含其他模板,对应的也是一个字字典。
- 注释,{{!注释名}},包含注释。
实例
以下为所写项目中的一个函数
// 整个过程的目的是将问题数据填充到HTML模板中,生成最终的HTML字符串,这样可以动态地生成包含问题列表信息的HTML内容。
void AllExpandHtml(const std::vector<struct Question> questions, std::string *html) {
// 1. 形成路径
std::string src_html = template_path + "all_questions.html";
// 2. 形成数据字典
// all_questions并没有具体的实际意义或作用于模板渲染过程中。它主要是用于识别或者描述这个TemplateDictionary对象。
// 在debug时帮助你找出是哪一个TemplateDictionary出现了问题,起到辅助标识的作用
ctemplate::TemplateDictionary root("all_questions");
for (const auto &q : questions) {
// 添加一个子字典,这个子字典表示一个题目的数据。
ctemplate::TemplateDictionary *sub = root.AddSectionDictionary("question_list");
// 设置子字典中的值,将问题的编号、标题和难度分别设置为 "number"、"title" 和 "star"。
sub->SetValue("number", q.__number);
sub->SetValue("title", q.__title);
sub->SetValue("star", q.__star);
}
// 3. 获取被渲染的html
//ctemplate::DO_NOT_STRIP 是在调用 ctemplate::Template::GetTemplate 函数时使用的一个标志,用于指示是否在加载模板时去除不可见的空格和换行符
ctemplate::Template *tpl = ctemplate::Template::GetTemplate(src_html, ctemplate::DO_NOT_STRIP);
// 4. 执行渲染
tpl->Expand(html, &root);
}
对应的前端:
{{#question_list}}
和{{/question_list}}
表示一个循环
<div class="question_list">
<h1>OnlineJudge题目列表</h1>
<table>
<tr>
<th class="item">题目编号</th>
<th class="item">题目标题</th>
<th class="item">题目难度</th>
</tr>
{{#question_list}}
<tr>
<td class="item">{{number}}</td>
<td class="item"><a href="/question/{{number}}">{{title}}</a></td>
<td class="item">{{star}}</td>
</tr>
{{/question_list}}
</table>
</div>
ctemplate
提供了一些高级功能,使得在模板中进行更灵活的文本生成成为可能。以下是一些常见的高级功能:
1. 循环结构:
在模板中使用循环结构,可以重复处理数据集中的每个元素。
模板文件示例 (template.tpl
):
<ul>
<?loop name="users" from="$users$">
<li><?=$users.name$>, Age: <?=$users.age$></li>
<?/loop?>
</ul>
C++ 代码:
ctemplate::TemplateDictionary dict("example");
// 假设 users 是一个 std::vector<ctemplate::TemplateDictionary>,每个字典包含 name 和 age。
dict.AddSectionDictionary("users");
for (const auto& user : users) {
ctemplate::TemplateDictionary* userDict = dict.AddSectionDictionary("user");
userDict->SetValue("name", user.name);
userDict->SetValue("age", user.age);
}
ctemplate::Template* tpl = ctemplate::Template::GetTemplate(
"path/to/your/template.tpl", ctemplate::DO_NOT_STRIP);
std::string output;
tpl->Expand(&output, &dict);
2. 条件语句:
在模板中使用条件语句,根据特定条件显示或隐藏部分内容。
模板文件示例 (template.tpl
):
<?if condition="$showDetails$"?>
<p>Details: <?=$details$></p>
<?/if?>
C++ 代码:
ctemplate::TemplateDictionary dict("example");
dict.SetValue("showDetails", true);
dict.SetValue("details", "Some details to show.");
ctemplate::Template* tpl = ctemplate::Template::GetTemplate(
"path/to/your/template.tpl", ctemplate::DO_NOT_STRIP);
std::string output;
tpl->Expand(&output, &dict);
3. 嵌套结构:
在模板中可以嵌套使用循环和条件语句,以实现更复杂的文本生成逻辑。
模板文件示例 (template.tpl
):
<ul>
<?loop name="groups" from="$groups$">
<li><?=$groups.name$>
<ul>
<?loop name="users" from="$groups.users$">
<li><?=$users.name$>, Age: <?=$users.age$></li>
<?/loop?>
</ul>
</li>
<?/loop?>
</ul>
C++ 代码:
ctemplate::TemplateDictionary dict("example");
// 假设 groups 是一个 std::vector<ctemplate::TemplateDictionary>,每个字典包含 name 和 users。
dict.AddSectionDictionary("groups");
for (const auto& group : groups) {
ctemplate::TemplateDictionary* groupDict = dict.AddSectionDictionary("group");
groupDict->SetValue("name", group.name);
groupDict->AddSectionDictionary("users");
for (const auto& user : group.users) {
ctemplate::TemplateDictionary* userDict = groupDict->AddSectionDictionary("user");
userDict->SetValue("name", user.name);
userDict->SetValue("age", user.age);
}
}
ctemplate::Template* tpl = ctemplate::Template::GetTemplate(
"path/to/your/template.tpl", ctemplate::DO_NOT_STRIP);
std::string output;
tpl->Expand(&output, &dict);
这些是 ctemplate
中一些高级功能的示例。你可以根据自己的需求使用这些功能,创建更复杂和灵活的模板。在实际使用中,你可能需要查阅 ctemplate
的详细文档以获取更多信息和示例。