Pull to refresh

htmlcxx базовое описание и основные приёмы использования

Htmlcxx представляет из себя небольшую библиотеку для парсинга HTML и CSS, написанную на С++ и для С++.
Библиотека весьма распространена и присутствует в большинстве репозиториев.
Библиотека обладает следующими положительными характеристиками:

  • STL-подобная навигация по DOM дереву
  • Способность точного восстановления исходного документа из распаршенного дерева
  • Парсинг атрибутов тегов
  • Удобный расчёт смещений тэгов в оригинальном документе


А также одной отрицательной, перечёркивающей все достоинства:
  • Полное отсутствие документации


Однако отсутствие документации легко объясняется её ненужностью. Правда до этой мысли надо дойти, а это не так уж и просто.
В этой статье я дам базовый пример использования библиотеки, а также укажу какую документацию использовать вместо несуществующей родной.

Итак, пример:
#include <htmlcxx/html/ParserDom.h>
// Тут ваш код, неймспейсы и прочее по вкусу
int main()
{
  std::string code = "<html><body>example</body></html>";
  htmlcxx::HTML::ParserDom parser;
  tree<htmlcxx::HTML::Node> dom = parser.parseTree(code);
  
  //Попробуем получить все ссылки
  tree<htmlcxx::HTML::Node>::iterator it = dom.begin();
  tree<htmlcxx::HTML::Node>::iterator end = dom.end();
  for (; it != end; ++it)
  {
  	if (it->tagName() == "A")
  	{
  		it->parseAttributes();
  		std::cout << it->attributes("href");
  	}
  }
}


Код вполне понятен, но совершенно недостаточен для написания чего-то полезного.
Для использования этой библиотеки мы должны посмотреть в код и обнаружить, что собственно дерево базируется на tree.hh.
И в дальнейшем мы можем воспользоваться замечательным документом за авторством Каспера Питерса, который вы сможете найти на сайте tree.phi-sci.com (на самом деле на этом статью можно завершать — я лишь хотел указать на этот документ, как на недостающее звено информации о библиотеке)
Я здесь приведу лишь базовые понятия, которые будут достаточны для начала работы с библиотекой.

На выходе из парсера мы получаем дерево. Узлы, которые находятся на одном уровне этого дерева называются «sibling». Узлы, которые, находятся уровнем ниже называются «children». И вот самое главное: библиотека предоставляет нам множество различных итераторов для прохода по дереву. Вот, то, чего не хватало в оригинальной доке.
Предположим у нас есть дерево вида:

  • root
    • A
      • B
      • C

    • D
      • E
      • F




Давайте посмотрим в какой очередности будет осуществлён проход по дереву различными итераторами:
  • pre_order_iterator — root A B C D E F
  • post_order_iterator -- B C A E F D root
  • breadth_first_iterator -- root A D B C E F
  • sibling_iterator — A D(если опустимся на уровень ниже root)
  • fixed_depth_iterator --A D(аналогично и тут)
  • leaf_iterator — B C E F

Осталось лишь добавить, что итераторы обладают конструкторами копирования, позволяющими преобразовывать различные типы итераторов друг в друга.

Теперь вы обладаете необходимым минимумом информации по этой библиотеке и знаете куда «копать» если он окажется недостаточным.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.