前面说了那么多,终于说到如何解析html表单信息了。
什么是表单信息呢,这里我们先要有一些概念:
如上图,这是一个QQ注册页面,注册页面当中需要我们填的空其实就是一个表单信息。
具体到html代码当中,如下
<form action="action_page.php"> First name:<br> <input type="text" name="firstname" value="Mickey"> <br> Last name:<br> <input type="text" name="lastname" value="Mouse"> <br><br> <input type="submit" value="Submit"> </form>
(html摘自w3cschool)
(上图摘自w3cschool)
一般而言,表单信息的标签都为input标签,或是select标签。当我们要上传表单的时候,主要post给服务器的是表单标签当中的name和value属性,如果我们要解析表单的话,只要将这两个属性解析出来就好。
在浏览器当中我们上传表单的过程大概是这样子的
其实就是吧我们刚才填入表单的数据post到服务器。
以下给出代码
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> #include <string.h> #include "gumbo.h" #define parse_h //检查select标签下被选中的option标签 void find_selected(GumboNode *node,char * str_value) { GumboVector *children; GumboAttribute *value; GumboNode *child; int i; children=&node->v.element.children; if(str_value!=NULL) { for(i=0;i<children->length;i++) { child=((GumboNode*)children->data[i]); if(child->v.element.tag==GUMBO_TAG_OPTION)//检查其是否为option标签 { if(gumbo_get_attribute(&child->v.element.attributes,"selected"))//检查option是否被选中 { if((value=gumbo_get_attribute(&child->v.element.attributes,"value"))!=NULL)//保存option标签的value值 { strcpy(str_value,(char *)value->value); return; }else{ strcpy(str_value," "); return; } } } } strcpy(str_value," "); } return; } //解析表单信息,将结果添加到链表当中 void findDataFormItem(GumboNode *node) { GumboVector *children; int i; GumboAttribute *name; GumboAttribute *value; GumboAttribute *type; GumboAttribute *checked; char str_value[100]; if(header==NULL) { printf("header is null/n"); return; } if(node->type!=GUMBO_NODE_ELEMENT) return;//如果节点不为元素节点就返回,至于什么是元素节点,请查找dom树的有关资料 children=&node->v.element.children;//获取子节点 if((node->v.element.tag==GUMBO_TAG_INPUT)&&(name=gumbo_get_attribute(&node->v.element.attributes,"name"))&&(value=gumbo_get_attribute(&node->v.element.attributes,"value")))//如果标签为input标签,并且有name和value属性 { if((type=gumbo_get_attribute(&node->v.element.attributes,"type")))//检查input标签类型 { //当input标签的类型为checkbox类型的时候,是有当checkbox被选中的时候,才将name和value添加到链表当中,其余,直接添加 if(strcmp((char*)type->value,"checkbox")) { printf("name=%s\n",(char *)name->value); printf("value=%s\n",(char *)value->value); } else { if((checked=gumbo_get_attribute(&node->v.element.attributes,"checked"))) { printf("name=%s\n",(char *)name->value); printf("value=%s\n",(char *)value->value); } } } } if((node->v.element.tag==GUMBO_TAG_SELECT)&& (name=gumbo_get_attribute(&node->v.element.attributes,"name")))//如果标签为select标签,并且有name属性 { find_selected(node,str_value);//检查select标签下的option标签,如果某个option标签的有selected属性(表示选项被选中),就将其value保存到链表当中 printf("name=%s\n",(char *)name->value); printf("value=%s\n",str_value); } //递归扫描 if(!(node->v.element.tag==GUMBO_TAG_SELECT)) { for(i=0;i<children->length;++i) { findDataFormItem((GumboNode*)(children->data[i]),header); } } } //解析html表单数据,并且将表单标签的name和value数据保存到一个链表当中 void ParseFormItems(char *htmlFile) { GumboOutput *DOMtree; DOMtree=gumbo_parse(htmlFile);//解析html数据成为一刻,dom树,要多了解的话应该查找一些有关html5 dom树的知识 findDataFormItem(DOMtree->root);//解析表单信息 gumbo_destroy_output(&kGumboDefaultOptions,DOMtree);//释放资源 }
大家一开始可能并不是十分了解gumbo解析html页面的逻辑,其实gumbo解析html页面也是根据dom树和html5的逻辑来的。
推荐一个html5标准的参考资料https://html.spec.whatwg.org/multipage/