轻量级标记扫描器:快速解析HTML/XML

在处理XML或HTML文本时,如果只需要找到某个词、标签或属性,使用完整的DOM编译器或SAX解析器可能过于复杂。此时,使用一个轻量级的标记扫描器是一个更好的选择。下面介绍的markup::scanner就是这样一个工具,它具有以下特点:

  • 在扫描过程中不分配任何内存。
  • 使用纯C++编写,不需要STL或其他工具库。
  • 速度快,扫描速度可达每秒40MB(取决于硬件)。
  • 简单易用。

如何使用

最好的解释方式是通过示例。首先,需要为扫描器声明一个输入流。以下是一个基于字符串的简单流示例:

struct str_istream : public markup::instream { const char* p; const char* end; str_istream(const char* src) : p(src), end(src + strlen(src)) {} virtual wchar_t get_char() { return p < end ? *p++ : 0; } };

以上代码定义了一个简单的字符串输入流。接下来,将编写一个程序,打印出输入HTML中的所有标记:

int main(int argc, char* argv[]) { str_istream si( "

Begin & back

" "" ); markup::scanner sc(si); bool in_text = false; while (true) { int t = sc.get_token(); switch (t) { case markup::scanner::TT_ERROR: printf("ERROR\n"); break; case markup::scanner::TT_EOF: printf("EOF\n"); goto FINISH; case markup::scanner::TT_TAG_START: printf("TAG START:%s\n", sc.get_tag_name()); break; case markup::scanner::TT_TAG_END: printf("TAG END:%s\n", sc.get_tag_name()); break; case markup::scanner::TT_ATTR: printf("\tATTR:%s=%S\n", sc.get_attr_name(), sc.get_value()); break; case markup::scanner::TT_WORD: case markup::scanner::TT_SPACE: printf("{%S}\n", sc.get_value()); break; } } FINISH: printf("--------------------------\n"); return 0; }

如所见,主要的工作方法是markup::scanner::get_token()。它扫描输入流并返回markup::scanner::token_type的值。

enum token_type { TT_ERROR = -1, TT_EOF = 0, TT_TAG_START, TT_TAG_END, TT_ATTR, TT_WORD, TT_SPACE, TT_DATA, TT_COMMENT_START, TT_COMMENT_END, TT_CDATA_START, TT_CDATA_END, TT_PI_START, TT_PI_END, TT_ENTITY_START, TT_ENTITY_END, };
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485