在我的应用程序需要解析简单的HTML代码,而无需使用尽可能少的外部库。 我的HTML看起来像
<p> First Content is P </p><h2>Header</h2><p> Text under header </p>
<h2>Header 2</h2><p> Paragraph </p>
<h3>yep</h3><p> no </p>
我的HTML只包含标签p, h2, h3
。 我有以下结构:
struct Elements {
std::string tag;
std::string content;
};
std::vector<Elements> elems;
所以我的目标是在解析载体应包含这样的数据的每个元素后:
tag = "h2"
content = "Header"
和
tag = "p"
content = "First Content is P"
PP:我需要在他们的HTML呈现的顺序的元素。
编辑:
我只是在JavaScript这样做,它的工作很好,但我已经基本不知道如何把它写在C ++:
var a = "<p> First Content is P </p><h2>Header</h2><p> Text under header </p>" +
"<h2>Header 2</h2><p> Paragraph </p>" +
"<h3>yep</h3><p> no </p>";
var output = [];
a.replace(/<\b[^>]*>(.*?)<\/(.*?)>/gmi, function(m, key, value) {
output.push({
tag: value,
data: key
});
})
/*
output:
{ tag: "p", data: "First Content is P"},
{ tag: "h2", data: "Header" }
.....
*/
只有这三个要素,并没有缺少结束标记。 这看起来好像此外,还有标签上的任何属性,甚至没有内部元素的任何元素。 里面有没有标签或者空白。
然后你不解析HTML。 您正在分析一种特殊的语言是HTML的一个子集(当然,即使没有真正的一个子集,因为您的文档不验证)。
你可能有一个很好的理由不希望使用HTML解析器来解析这个特殊的语言。 例如,对于一个完整的HTML解析器的代码是大十岁上下,或许本来没有需要是你写的非常小的嵌入式设备上。 更有可能的是,这是一个学习的任务,其目标是为您操作字符串不选择生产所需的输出的最佳工具。 我会认为你必须避免使用HTML库无需作进一步考虑为什么。
那么,如何分析这种特殊的语言? 如何解析什么。 鉴于我上面列出的所有限制,你可以做到这一点很干脆:
- 三个子任一项所述的字符串中查找第一个实例
<p>
<h2>
<h3>
这是你的开始标记。 - 找到对应的关闭标记的第一个实例。
- 介于两者之间的是元素的内容。 在您的例子中,你另外在内容的每个端部修整空白。 构造一个
Elements
对象,并把它添加到您的载体(顺便说一句可以考虑使用一个单一的类名,不是复数)。 - 重复的字符串的其余部分。
而已。 你可以做的是使用正则表达式,但我总的感觉是,既然你说你想要做的在C ++中,那么你可能也只是做它在C ++。 没有必要把另一种语言进去,优点和正则表达式的限制什么,他们肯定是另一种语言。
不过 ,也许我上面列出的额外限制不能保证。 如果你以后要支持内标签的空间? 和属性? 而XML命名空间? 和评论? 然后,你会希望你只使用一个HTML解析器。 因此你的HTML固定琐碎子做的是从你的显著子集或一个有可能成为未来显著做什么不同。
仅仅是一个建议。 提速解析器,改变struct Elements
喜欢的东西
struct Node { const char * ptrToNodeStart; int nodeLen; Entity() ... etc}
struct Elements {
Node tag;
Node content; };
其主要思想是,以避免标签的内存分配和内容,因为你已经在内存中整个文档。 只要保持它的存在,并与指针操作。 它的速度要快得多。 在指针上,解析过程将结束单一的分配完成之前。 当你的解析器通过文件运行时,它会创建新的节点(会从预分配的池),并会把目前PTR到节点:: ptrToNodeStart。 当新的节点发生(或目前已关闭),你修复节点:: nodeLen和完整的元素。 这是这个想法。 用结构元素严重的问题,它不适合于HTML结构,因为HTML节点通常包括其它节点,所以它需要进行嵌套元素。 解析HTML是有趣的任务,甚至还有吨解析器已经在市场上。 祝好运。