Задача преобразования 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.