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