本帖最后由 海岸的声音 于 2011-2-10 17:51 编辑
根据标签名称取标签类型的getHtmlTagTypeFromName()方法,就非常直白了,查表,逐一识别:
- view plaincopy to clipboardprint?
- //[virtual]
- HtmlTagType HtmlParser::getHtmlTagTypeFromName(const WCHAR* szTagName)
- {
- //todo: uses hashmap
- struct N2T { const WCHAR* name; HtmlTagType type; };
- static N2T n2tTable[] =
- {
- { L"A", TAG_A },
- { L"FONT", TAG_FONT },
- { L"IMG", TAG_IMG },
- { L"P", TAG_P },
- { L"DIV", TAG_DIV },
- { L"SPAN", TAG_SPAN },
- { L"BR", TAG_BR },
- { L"B", TAG_B },
- { L"I", TAG_I },
- { L"HR", TAG_HR },
- };
- for(int i = 0, count = sizeof(n2tTable)/sizeof(n2tTable[0]); i < count; i++)
- {
- N2T* p = &n2tTable[i];
- if(wcsicmp(p->name, szTagName) == 0)
- return p->type;
- }
- return TAG_UNKNOWN;
- }
复制代码 请注意,上文负责解析属性表的parseNodeProps()函数,和负责识别标签名称的getHtmlTagTypeFromName()函数,都是虚函数(virtual method)。我(liigo)这么设计是有深意的,给使用者留下了很大的定制空间,可以自由发挥。例如,通过在子类中覆盖/覆写(override)parseNodeProps()方法,可以采用更好的解析算法,或者干脆不做任何处理以提高HTML解析效率——将来某一时间可以调用基类同名函数专门解析特定标签的属性表;例如,通过在子类中覆盖/覆写(override)getHtmlTagTypeFromName()方法,使用者可以选择识别跟多的标签名称(包括自定义标签),或者识别更少的标签名称,甚至不识别任何标签名称(以便提高解析效率)。以编写网络爬虫程序为实例,它多数情况下通常只需识别<A>标签及其属性就足够了,没必要浪费CPU运算去识别其它标签、解析其他标签属性。
至于HTML文本解析器的用途,我目前想到的有:用于HTML格式检查或规范化,用于重新排版HTML文本,用于编写网络爬虫程序/搜索引擎,用于基于HTML模板的动态网页生成,用于HTML网页渲染前的基础解析,等等。
下面附上完整源码,仅供参考,欢迎指正。
HtmlParser.h:
- + expand sourceview plaincopy to clipboardprint?
复制代码 HtmlParser.cpp:
- + expand sourceview plaincopy to clipboardprint?
复制代码
补记:本文所提供的源代码,目前有未完善之处,如没有考虑到内嵌JavaScrip代码和HTML注释中的特殊字符(特别是尖括号)对解析器的影响,另外还可能有其他疏漏和bug,故代码仅可用于学习参考研究使用。我今后也将继续改进此HTML语法解析器。特此声明。
|