HtmlRender - c++实现的html生成类

HtmlRender

CppTinParser/render.hpp中定义和实现。

使用c++实现的简易Html编辑类。

简介

目前,c++有几个Html解析器,而少见便捷规范的html生成器,HtmlRender则提供了一个简单的、规范的html内容生成器。用c++实现html内容生成器,并不是简单的字符串拼接,这样会导致代码编写不规范、易读性下降,而且无法应对复杂html生成任务。HtmlRender借鉴了python的第三方html编写库——dominate


使用接口

初始化

HtmlRender* item = HtmlRender(string tag, string content, map<string,string> kws, bool onetag=false, bool pre=false)
//tag 标签名称,如果为空字符串,则在生成时直接产生content,不添加标记
//content 标签内容
//kws 标签参数
//onetag 是否为单标签,比如<br>, <hr>等
//pre 是否显示为原文本

生成html文本

string result = HtmlRender.render()

该函数将生成并返回该HtmlRender所包含的html文本内容。一般应只用tag = "html"HtmlRender使用该函数,以此来实现完整的html文本。当然,任意HtmlRender实例均可,单标签也可使用该函数,但是生成内容将大概率出现错误。

添加子元素

为了方便操作,HtmlRender使用list作为容器来存取子元素指针,这里的子元素同样是HtmlRender。具体增加代码如下:

HtmlRender* subitem = new HtmlRender(...)
item.add(subitem)

如果父元素本身就是通过new创建,则使用如下代码:

item->add(subitem)

设置标签元素内容和参数

设置内容:

item.configcnt(string content)

设置参数:

item.configkws(map<string, string> kws)

获取父元素指针

除了顶级元素,任何一个标签元素在被使用add方法后,都会有明确的父元素。

通过如下代码获取父元素指针:

HtmlRender* p_item = subitem->parent()
//p_item == &item

获取子元素指针列表

如果一个元素使用了add方法,则必然含有子元素。

使用如下代码获取子元素指针列表

list<HtmlRender*> children = item.children()

实现原理

添加子元素

获取子元素指针,在子元素指针列表中添加该指针。

void HtmlRender::add(HtmlRender* item) {//添加html内容this->htmlcontent.push_back(item);item->_parent = this;
}

渲染

首先生成元素自身标签、参数、内容,然后遍历子元素指针列表,获取所有子元素以及多级子元素的渲染生成内容,最后加上自身结束标签(如果有的话)。

string HtmlRender::render() {//渲染为html文本if (this->tag == ""){return this->content;}string htmltext = "<" + this->tag;for (auto &kw : this->kws) {htmltext += " " + kw.first + "=\"" + kw.second + "\"";}htmltext += ">";htmltext += this->content;for (auto item = this->htmlcontent.begin(); item != this->htmlcontent.end(); ++item) {string subtext = (*item)->render();htmltext += "\n" + subtext;}if (this->onetag){//单标签htmltext += "\n";}else{htmltext += "\n</" + this->tag + ">";}return htmltext;
}

示例

测试代码:

int main(){HtmlRender html = HtmlRender("html", "", {});HtmlRender* head = new HtmlRender("head", "", {});HtmlRender* title = new HtmlRender("title", "TinML", {});head->add(title);html.add(head);HtmlRender* body = new HtmlRender("body", "", {});html.add(body);HtmlRender* t1 = new HtmlRender("h1", "TITLE", {});body->add(t1);for (int i=0; i<10; i++){HtmlRender* p = new HtmlRender("p", "paragraph - " + to_string(i), {});body->add(p);}string htmltext = html.render();cout << htmltext <<endl;return 0;
}

结果:

<html>
<head>
<title>TinML
</title>
</head>
<body>
<h1>TITLE
</h1>
<p>paragraph - 0
</p>
<p>paragraph - 1
</p>
<p>paragraph - 2
</p>
<p>paragraph - 3
</p>
<p>paragraph - 4
</p>
<p>paragraph - 5
</p>
<p>paragraph - 6
</p>
<p>paragraph - 7
</p>
<p>paragraph - 8
</p>
<p>paragraph - 9
</p>
</body>
</html>

主要源码

string subreplace(std::string resource_str, std::string sub_str, std::string new_str){string dst_str = resource_str;string::size_type pos = -1;//这里要专门处理&转义后仍存在的&符号,所以find使用了poswhile((pos = dst_str.find(sub_str, pos+1)) != std::string::npos)   //替换所有指定子串{dst_str.replace(pos, sub_str.length(), new_str);}return dst_str;
}class HtmlRender {//html编辑类
public:HtmlRender()=default;HtmlRender(string tag, string content, map<string,string> kws, bool onetag=false, bool pre=false){this->tag = tag;// this->content = content;// this->kws = kws;this->pre = pre;if (pre){//原文本内容this->content = content;}else{this->load_content(content);}this->load_kws(kws);this->onetag = onetag;this->_parent = NULL;}HtmlRender* _parent;//父节点string render();//输出html文本void add(HtmlRender* item);//添加html内容void configcnt(string content);//配置html内容void configkws(map<string, string> kws);//配置html内容HtmlRender* parent();list<HtmlRender*> children();//获取子HtmlRender内容
private:list<HtmlRender*> htmlcontent;//html文件内容string tag;//html标签string content;//标签内容map<string, string> kws;//html关键字bool onetag;//是否为单标签bool pre;//是否为原文本内容const map<string, string> ascii_ent = { { "\"", "quot" }, { "\'", "apos" }, { "&", "amp" }, { "<", "lt" }, { ">", "gt" } };//ascii转义void load_content(string content);//加载内容void load_kws(map<string, string> kws);//加载关键字string escape_ascii(string content);//转义ascii字符};string HtmlRender::render() {//渲染为html文本if (this->tag == ""){return this->content;}string htmltext = "<" + this->tag;for (auto &kw : this->kws) {htmltext += " " + kw.first + "=\"" + kw.second + "\"";}htmltext += ">";htmltext += this->content;for (auto item = this->htmlcontent.begin(); item != this->htmlcontent.end(); ++item) {string subtext = (*item)->render();htmltext += "\n" + subtext;}if (this->onetag){//单标签htmltext += "\n";}else{htmltext += "\n</" + this->tag + ">";}return htmltext;
}void HtmlRender::add(HtmlRender* item) {//添加html内容this->htmlcontent.push_back(item);item->_parent = this;
}void HtmlRender::configcnt(string content) {//配置html内容if (this->pre){//原文本内容this->content = content;}else{string ascii_ent = this->escape_ascii(content);this->content = ascii_ent;}}void HtmlRender::configkws(map<string, string> kws) {//配置html内容for (auto &kw : kws) {string value = kw.second;string ascii_ent = this->escape_ascii(value);kw.second = value;}this->kws = kws;}HtmlRender* HtmlRender::parent() {return this->_parent;
}list<HtmlRender*> HtmlRender::children() {return this->htmlcontent;
}void HtmlRender::load_content(string content) {//加载内容string ascii_ent = this->escape_ascii(content);this->content = ascii_ent;}void HtmlRender::load_kws(map<string, string> kws) {//加载关键字for (auto &kw : kws) {string value = kw.second;string ascii_ent = this->escape_ascii(value);kw.second = value;}this->kws = kws;}string HtmlRender::escape_ascii(string content) {//转义ascii字符for (auto &item : this->ascii_ent) {content = subreplace(content, item.first, "&" + item.second + ";");}return content;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/428104.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大厂程序员的健身之路

大厂程序员的健身之路 基本信息饮食正餐营养补剂 睡眠训练计划 基本信息 健身时间&#xff1a;2023.03 -> 2024.09体重变化&#xff1a;52kg -> 67kg 饮食 正餐 早餐&#xff1a;不吃午餐&#xff1a;两碗米饭 鱼/鸡肉 蔬菜 酸奶晚餐&#xff1a;两碗米饭 鱼/鸡肉…

java之杨辉三角问题

给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 如何实现呢&#xff1f; 思路&#xff1a;首先&#xff0c;我们可以将杨辉三角视作i行j列的二维数组。除了第一行和第二行之外&am…

BuripSuiteProfessional 抓取HTTPS配置

1.电脑拿开代理 谷歌为例 点击三点-设置 -输入代理--点击代理设置 打开手动代理---IP ,端口如图-点击保存 2.下载CA证书 打开代理后,谷歌浏览器打开,输入/burp--如下图-点击CA证书下载证书 选择下载目录--桌面 3.安装CA证书 谷歌浏览器中点开设置-输入证书-点击安全 点击…

传知代码-多示例AI模型实现病理图像分类

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 概述 本文将基于多示例深度学习EPLA模型实现对乳腺癌数据集BreaKHis_v1的分类。EPLA模型是处理组织病理学图像的经典之作。EPLA模型是基于多示例学习来进行了&#xff0c;那么多示例学习模型对处理病理学图像具有…

优化算法(一)—遗传算法(Genetic Algorithm)附MATLAB程序

遗传算法&#xff08;Genetic Algorithm, GA&#xff09;是一种启发式搜索算法&#xff0c;用于寻找复杂优化问题的近似解。它模拟了自然选择和遗传学中的进化过程&#xff0c;主要用于解决那些传统算法难以处理的问题。 遗传算法的基本步骤&#xff1a; 初始化种群&#xff0…

GNN-RAG:用于大模型推理的图神经检索

GNN-RAG&#xff1a;用于大模型推理的图神经检索 秒懂大纲提出背景解法拆解全流程优化创意总结 论文&#xff1a;GNN-RAG: Graph Neural Retrieval for Large Language Model Reasoning 代码&#xff1a;https://github.com/cmavro/GNN-RAG 秒懂大纲 ├── GNN-RAG【主题】…

美国站群服务器优化技巧解析

美国站群服务器&#xff0c;作为专为管理多个网站而设计的托管解决方案&#xff0c;其优化对于提升网站性能和用户体验至关重要。以下是一些关键的优化技巧&#xff1a; 首先&#xff0c;硬件配置是基础。选择高性能的CPU、大容量的内存以及高速的硬盘(如SSD)是提升服务器运算速…

Java 集合详解

目录 一. 概述 二. Collection接口实现类 三. Map接口实现类 四. 线程安全集合 五. List接口下集合实现原理 1. ArrayList实现原理 1.1. 基于动态数组 1.2. 随机访问 1.3. 添加元素 1.4. 删除元素 1.5. 迭代器 1.6. 克隆和序列化 1.7. ArrayList简单使用 2. Link…

Linux环境变量进程地址空间

目录 一、初步认识环境变量 1.1常见的环境变量 1.2环境变量的基本概念 二、命令行参数 2.1通过命令行参数获取环境变量 2.2本地变量和内建命令 2.3环境变量的获取 三、进程地址空间 3.1进程&#xff08;虚拟&#xff09;地址空间的引入 3.2进程地址空间的布局和理解 …

11年计算机考研408-数据结构

设执行了k次。 解析&#xff1a; d要第一个出&#xff0c;那么abc先入栈&#xff0c;d入栈然后再出栈&#xff0c;这前面是一个固定的流程&#xff0c;后面就很灵活了&#xff0c;可以ecba&#xff0c;ceba&#xff0c;cbea&#xff0c;cbae。 答案是4个序列。 解析&#xff1a…

【论文阅读】PERCEIVER-ACTOR: A Multi-Task Transformer for Robotic Manipulation

Abstract transformers凭借其对大型数据集的扩展能力&#xff0c;彻底改变了视觉和自然语言处理。但在机器人操作中&#xff0c;数据既有限又昂贵。通过正确的问题表述&#xff0c;操纵仍然可以从变形金刚中受益吗&#xff1f;我们使用peract来研究这个问题&#xff0c;peract…

Spring Boot利用dag加速Spring beans初始化

1.什么是Dag&#xff1f; 有向无环图(Directed Acyclic Graph)&#xff0c;简称DAG&#xff0c;是一种有向图&#xff0c;其中没有从节点出发经过若干条边后再回到该节点的路径。换句话说&#xff0c;DAG中不存在环路。这种数据结构常用于表示并解决具有依赖关系的问题。 DAG的…

elasticsearch同步mysql方案

文章目录 1、1. 使用数据库触发器2. 使用定时任务3. 监听MySQL二进制日志&#xff08;binlog&#xff09;4. 使用数据管道5. 使用第三方工具或服务6. 编写自定义脚本注意事项 2、1. 使用Logstash步骤&#xff1a;示例配置&#xff1a; 2. 使用Debezium步骤&#xff1a; 3. 自定…

【Redis入门到精通三】Redis核心数据类型(List,Set)详解

目录 Redis数据类型 ​编辑 1.List类型 &#xff08;1&#xff09;常见命令 &#xff08;2&#xff09;内部编码 2.Set类型 &#xff08;1&#xff09;常见命令 &#xff08;2&#xff09;内部编码 Redis数据类型 查阅Redis官方文档可知&#xff0c;Redis提供给用户的核…

JavaScript - Document文档操作

1. 前言 ​​​​​​​ 编写网页时&#xff0c;我们需要时刻操作文档进而完成我们想要的效果。这就是通过文档对象模型实现&#xff0c;使用Document对象控制HTML以及样式信息的API 2. Document的树结构 在了解Document文档对象模型之前&#xff0c;我们先了解Dom的树结构 …

使用scp命令从本地往服务器传输文件失败

解决办法&#xff1a; 找到这个文件&#xff0c;打开&#xff0c;将里面的服务器ip对应的一行数据删掉即可。

(c语言+数据结构链表)项目:贪吃蛇

目录 1.项目背景 2.游戏效果演⽰ 3. ⽬标 4. 技术要点 5. Win32 API介绍 5.1 Win32 API 5.2 控制台程序 5.3 控制台屏幕上的坐标COORD 5.4 GetStdHandle 5.5 GetConsoleCursorInfo 5.5.1 CONSOLE_CURSOR_INFO 5.6 SetConsoleCursorInfo 5.7 SetConsoleCursorPositi…

d3dcompiler47dll丢失怎么解决,详细介绍6种解决方案

在电脑使用过程中&#xff0c;我们可能会遇到各种问题&#xff0c;其中之一就是系统提示某个文件缺失。其中&#xff0c;d3dcompiler_47.dll是许多用户经常遇到的问题之一。这个文件是DirectX组件的一部分&#xff0c;如果缺失&#xff0c;可能会导致游戏或应用程序无法正常运行…

Qt/C++ 多线程同步机制详解及应用

在多线程编程中&#xff0c;线程之间共享资源可能会导致数据竞争和不一致的问题。因此&#xff0c;采用同步机制确保线程安全至关重要。在Qt/C中&#xff0c;常见的同步机制有&#xff1a;互斥锁&#xff08;QMutex、std::mutex&#xff09;、信号量&#xff08;QSemaphore&…

Ansbile-变量

文章目录 一、Ansible的常量&#xff08;内置的变量&#xff09;有哪些&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1…