Gumbo HTML5 парсер от Google

Gumbo парсер HTML5 от Google написанный на Си, и не имеющий никаких зависимостей, кроме компилятора C99.
Правда под MSVC компилировать следует в режиме C++.

Страница проекта, мои Cmake скрипты сборки.

Пользоваться Gumbo, не просто, а очень просто(если конечно же есть опыт использования XML DOM парсеров).

Парсинг и построение дерева производиться функцией gumbo_parse, если нужно с определенными опциями gumbo_parse_with_options. Освобождение ресурсов производиться функцией gumbo_destroy_output.

std::string contents;</pre>
in.seekg(0, std::ios::end);
contents.resize(in.tellg());
in.seekg(0, std::ios::beg);
in.read(&contents[0], contents.size());
in.close();

GumboOutput* output = gumbo_parse(contents.c_str());
do_something(output->root);
gumbo_destroy_output(&kGumboDefaultOptions, output);

Простой рекурсивный обход дерева

void do_something(const GumboNode* node)
{
if (node->type != GUMBO_NODE_ELEMENT)
{
return;
}

const GumboVector* children = &node->v.element.children;
for (size_t i = 0; i < children->length; ++i)
{
do_something(static_cast<GumboNode*>(children->data[i]));
}
}

Узел может быть следующих типов:

  • GUMBO_NODE_DOCUMENT документ,
  • GUMBO_NODE_ELEMENT элемент,
  • GUMBO_NODE_TEXT текст,
  • GUMBO_NODE_CDATA CDATA хранимая в GumboText,
  • GUMBO_NODE_COMMENT комментарий хранимый в GumboText,
  • GUMBO_NODE_WHITESPACE пробельные символы хранимые в GumboText.

Данные хранятся в поле v, которое представлено объединением


union
{
 GumboDocument document
 GumboElement element
 GumboText text
}

Если узел GumboText и хочется вытащить текст, то node->v.text. Стоит отметить, что UTF-8 пакуется в char*.

Основные поля GumboElement:

GumboVector children
GumboTag tag
GumboSourcePosition start_pos
GumboSourcePosition end_pos
GumboVector attributes

Тут в принципе все понятно. children вектор детей; tag перечисление тегов GUMBO_TAG_A,GUMBO_TAG_HR, GUMBO_TAG_IMG и т.д.; start_pos и end_pos позиция тега в html, содержит номер строки и номер столбца(удобное представление для человека), а так же смещение от начала html документа (очень удобно, если например хочется выдрать кусок HTML кода), attributes вектор атрибутов.
Для вытаскивания значения атрибута существует функция gumbo_get_attribute, которая возвращает атрибут по строке, или NULL если заданного атрибута там нет.
Пример

GumboAttribute* href;
if (node->v.element.tag == GUMBO_TAG_A
&& (href = gumbo_get_attribute(&node->v.element.attributes, "href")))
{
std::cout << href->value << std::endl;
}
Реклама