ctemplate的使用

CTemplate是一种简单但功能强大的模板引擎,它是Google制作的一个开源C++库,广泛用于各种HTML模板解析和生成。CTemplate的主要优点是简单和灵活。它将模板和逻辑分开,使得页面布局和细节(HTML)与控制流、条件等逻辑分离,使软件的维护和修改变得更容易。

使用CTemplate的基本步骤如下:

创建模板文件:模板文件是普通的文件,比如一个HTML文件。在你想插入变量的地方使用{{VARIABLE_NAME}}的形式。

例如,在一个HTML模板中,你可以写

 <h1>{{TITLE}}</h1> <p>{{CONTENT}}</p>

在代码中填充模板:首先,你需要创建一个TemplateDictionary的实例,并为其添加变量。

 #include  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,每个字典包含 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,每个字典包含 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 的详细文档以获取更多信息和示例。