Gumbo结构关系图如下:
测试htm文件内容如下(a.html):
<html>
<head>
<title> I'm a title</title>
</head>
<body link="#0000cc">
I'm a body text
<div>
</div>
</body>
</html>
代码如下(mian.cpp):
#include <QCoreApplication>
#include <QFile>
#include <QDebug>
#include <iostream>
#include "gumbo/gumbo.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFile file("a.html");
if (!file.open(QFile::ReadOnly)){
qDebug()<<"open file failed!";
return -1;
}
QByteArray html = file.readAll();
std::cout<<html.toStdString();
int input_length = html.length();
GumboOutput* output = gumbo_parse_with_options(
&kGumboDefaultOptions, html.toStdString().c_str(), input_length);
// ===== start
const GumboVector *root_children = &output->root->v.element.children;
GumboNode* head = NULL;
for (int i = 0; i < root_children->length; ++i) {
GumboNode* child =(GumboNode*) root_children->data[i];
if (child->type == GUMBO_NODE_ELEMENT/* && child->v.element.tag == GUMBO_TAG_HEAD*/) {
std::cout<<"tag:"<<gumbo_normalized_tagname(child->v.element.tag)<<std::endl;
// node children start =====
// if (child->v.element.tag == GUMBO_TAG_HEAD){
GumboVector *head_children = &child->v.element.children;
for(int i=0; i<head_children->length; ++i){
GumboNode *child2 = (GumboNode*)head_children->data[i];
if (child2->type != GUMBO_NODE_ELEMENT && child2->type != GUMBO_NODE_DOCUMENT)
{
//节点结束时会换行,换行、空白符也算上是一个节点,类型是:GUMBO_NODE_WHITESPACE
std::cout<<"node is text:"<<child2->v.text.text<<std::endl;
continue;
}
std::cout<<"tag:"<<gumbo_normalized_tagname(child2->v.element.tag)<<std::endl;
if (child2->type == GUMBO_NODE_ELEMENT/* && child2->v.element.tag == GUMBO_TAG_TITLE*/)
{
// 元素里面的文本,例如<head>I'm a title</head>,里面的文本也是作为<head>元素里的子节点
GumboNode * title_node = (GumboNode*)child2->v.element.children.data[0];
if(title_node && title_node->type == GUMBO_NODE_TEXT){
std::cout<<"tag is text:"<<title_node->v.text.text<<std::endl;
}
}
}
//}
//break;
// node childre end =====
}
}
// ===== end
gumbo_destroy_output(&kGumboDefaultOptions, output);
//free(input);
return 0;
}
Gumbo说明:
1、整个html文档,就是Gumbo的文档节点,是<html></html>的全部,节点类型是:GUMBO_NODE_DOCUMENT
2、每个标签(例如:<head><body>)是一个节点,节点类型是:GUMBO_NODE_ELEMENT。标签里面的的属性定义是属性。
3、标签的子节点是标签括起来的部分,包括标签的换行"\n"(标签类型为:GUMBO_NODE_WHITESPACE),标签里面的文本(标签为元素标签,并且tag是文本)。
例如上面的html代码:
<html></html>是文档节点,换行"\n"、<head>和<body>是其子节点,节点类型分别是:GUMBO_NODE_WHITESPACE、GUMBO_NODE_ELEMENT和GUMBO_NODE_ELEMENT。
<head>标签节点的子节点是:换行"\n",<title>、文本节点(” I'm a title“)。
运行结果:
其中:
tag:head
node is text:
这里有两次换行,一次是这个节点本身是换行,另外是代码程序的换行。