Задача преобразования HTML-форматированного текста в XHTML появилась в связи с тем, что нужно было вставлять в XML блоки форматированного текста. (Про чтение таких блоков при SAX-разборе я написал статью: http://lj.rossia.org/users/shestero/141
Для выполнения этой задачи на C++ я успешно приминил бесплатную библиотку Tidy. К сожалению разработка её остановилась в начале 2009, но для моей задачи она сгодилась.
Я использовал MinGW, компилировал из коммандной строки-консоли Qt 4.8.3 под Windows 7.
Так как исходники уже довольно древние, при компиляции возникают небольшие загвоздки. Вот пошаговая инструкция, как я делал:
1. Использовал последний tarbar-архив из CSV (март 2009).
2. После распаковки надо создать вручную директории obj (где Makefile) и bin c lib (в директории tidy) (сами они не создаются)
3. Я использовал Makefile для gmake, но его пришлось изрядно поправить. Также для компиляции в MinGW пришлось поправить директиву выбора блока в файле src/mappedio.c. Исправленные файлы я выложил в архив tidy-changes.7z [здесь].
4. Для сборки библиотеки запустите make из директории build\gmake.
Вот код на C++, обеспечивающий конвертацию:
// Convert HTML to XHTML and clean up using libTidy #include <tidy.h> #include <buffio.h> string CleanHTML(const char *html) { // Initialize a Tidy document TidyDoc tidyDoc = tidyCreate(); TidyBuffer tidyOutputBuffer = {0}; // Configure Tidy // The flags tell Tidy to output XML and disable showing warnings bool configSuccess = tidyOptSetBool(tidyDoc, TidyXmlOut, yes) && tidyOptSetBool(tidyDoc, TidyQuiet, yes) && tidyOptSetBool(tidyDoc, TidyNumEntities, yes) && tidyOptSetBool(tidyDoc, TidyShowWarnings, yes) // no ;//&& tidyOptSetValue(tidyDoc,TidyCharEncoding, "utf8"); int tidyResponseCode = -1; // Parse input if (configSuccess) tidyResponseCode = tidyParseString(tidyDoc, html); // Process HTML if (tidyResponseCode >= 0) tidyResponseCode = tidyCleanAndRepair(tidyDoc); // Output the HTML to our buffer if (tidyResponseCode >= 0) tidyResponseCode = tidySaveBuffer(tidyDoc, &tidyOutputBuffer); // Any errors from Tidy? if (tidyResponseCode < 0) // Tidy encountered an error while parsing an HTML throw tidyResponseCode; // Grab the result from the buffer and then free Tidy's memory std::string tidyResult = (char*)tidyOutputBuffer.bp; tidyBufFree(&tidyOutputBuffer); tidyRelease(tidyDoc); return tidyResult; } // ................ // Convert HTML to XHTML and clean it // see also: https://bugs.webkit.org/show_bug.cgi?id=44876 string xhtml; try { xhtml = CleanHTML( html ); } catch (int e) { cerr << "Clean HTML error (from libTidy): " << e << endl; }Добавлю, что в моём случае обработка UTF-8 символов (кирилицы) в приложении, запущенном под Windows 7 x64 происходила не правильно (они конвертировались в кодовые &-представления побайтно). Так как мне это не было нужно в тот момент, я не стал разбираться в чём там дело, возможно просто в системных настройках локалей или в каких-то параметрах запуска библиотечных функций или компиляции. Вроде бы Tidy поддерживает UTF-8. Для обработки кириличных HTML-текстов также можно перевести их в однобайтовую кодировку, например в CP-1251.