引言
在HtmlRender - c++实现的html生成类一文中,我提到为了用c++实现TinML转html,自行构建了一个简易html编辑类。现在,我将其单独分离出来进行维护,并做了很多改进。
项目地址:cppHtmlBuilder-Gitee。
特性概要
- 自由指定html标签名称、参数、参数值
- 动态添加或修改标签参数-值、内容
- 动态添加、修改、删除子元素
- 随时生成html文本
- 可获取亲元素、所有子元素
以上特性借鉴了python-dominate和rust-build_html。
HtmlElement
HtmlElement是唯一类,用来动态构建html。允许三种初始化:
cpp
HtmlElement()=default;
HtmlElement(std::string tag, std::string content="", bool onetag=false, bool pre=false){
// tag 标签
// content 内容
// onetag 是否为单标签
// pre 是否直接写入内容而不用转义
}
HtmlElement(std::string tag, std::string content, std::map<std::string,std::string> kws, bool onetag=false, bool pre=false){
// kws 参数名-值,...
}
由于内部操作所有元素实例均以指针形式存在。所有元素尽可能创建在堆上,每个元素销毁时会自动销毁下辖所有元素。
输出字符串
cpp
std::string HtmlElement::render(std::string split_s="\n");
// split_s 间隔文本
该方法将本标签的当前状态输出为字符串,例如:
cpp
HtmlElement html = HtmlElement{"html"};
html.add(new HtmlElement{"div"});
cout << html.render() << endl;
/*
<html>
<div></div>
</html>
*/
添加子元素
有两种方法添加子元素:直接添加和链式添加。
直接添加
cpp
void HtmlElement::add(HtmlElement* item);
链式添加
cpp
HtmlElement* HtmlElement::add_with(HtmlElement* item);
// return this
使用add_with会返回自身指针,因此可用于链式添加,例如:
cpp
HtmlElement root = {"html"};
root.add((new HtmlElement{"head"})
->add_with(new HtmlElement{"title", "My Page"})
->add_with(new HtmlElement{"meta"})
->add_with(new HtmlElement{"meta"}));
cout << root.render() << endl;
/*
<html>
<head>
<title>My Page</title>
<meta></meta>
<meta></meta>
</head>
</html>
*/
该功能借鉴rust-
build_html。
设置内容
cpp
void HtmlElement::configcnt(std::string content);
设置所有参数
cpp
void HtmlElement::configkws(std::map<std::string, std::string> kws);
获取亲标签
cpp
HtmlElement* HtmlElement::parent();
获取所有子元素
cpp
std::list<HtmlElement*>& HtmlElement::children()
示例
cpp
#include <iostream>
#include <htmlbuilder.hpp>
using namespace std;
int main() {
HtmlElement root = {"html"};
root.add((new HtmlElement{"head"})->add_with(new HtmlElement{"title", "My Page"}));
HtmlElement* body = new HtmlElement{"body"};
root.add(body);
HtmlElement* div = new HtmlElement{"div"};
body->add(div);
div->configkws({{"id", "main"}, {"class", "container<>"}});
div->configcnt("&<html><div>content内容&");
div->add(new HtmlElement{"h1", "cpphtmlbuilder"});
// 添加列表
HtmlElement* ul = new HtmlElement{"ul"};
div->add(ul);
for (int i = 0; i < 10; i++) {
ul->add(new HtmlElement{"li", to_string(i)});
}
// 删除倒数第二个li
{
auto it = prev(ul->children().end(), 2);
auto element = *it;
ul->children().erase(it);
delete element;// 仍在堆上,需要手动释放
}
div->add(new HtmlElement{"", "content内容,只要标签名为空即可"});
auto result = root.render();
cout << result << endl;
}
输出内容:
html
<html>
<head>
<title>My Page</title>
</head>
<body>
<div class="container<>" id="main">&<html><div>content内容&
<h1>cpphtmlbuilder</h1>
<ul>
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>9</li>
</ul>
content内容,只要标签名为空即可
</div>
</body>
</html>