Преобразование Unicode в ANSI при получении содержимого элемента body в Delphi
Вопрос, поднятый в данном запросе, заключается в проблеме преобразования содержимого элемента body HTML-документа в строку ANSI-формата в среде Delphi. При использовании метода innerHTML для получения содержимого элемента body, содержащего Unicode-символы, возвращается BSTR, который содержит уже преобразованные символы в соответствующие Unicode-значения, а не их строковое представление.
Пример HTML-разметки с Unicode-символом:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML xmlns:o = "urn:schemas-microsoft-com:office:office">
<HEAD>
<META content="text/html; charset=windows-1251" http-equiv=Content-Type>
<META name=GENERATOR content="MSHTML 9.00.8112.16441"></HEAD>
<BODY>
<P>ψ</P>
</BODY>
</HTML>
Символ ψ вставляется с помощью IHTMLTxtRange.pasteHTML, и при попытке получить innerHTML элемента body ожидается получить строку <P>ψ</P>, однако фактически возвращается Unicode BSTR, где символ ψ (ψ) представлен Unicode-значением $03C8.
Альтернативный ответ
Попытка использования innerText также не приводит к успеху, так как возвращается текст без HTML-разметки.
Подтвержденный ответ
Для решения данной проблемы можно использовать интерфейс IPersistStream для получения исходного HTML-кода в виде массива байтов. Ниже приведен пример функции, которая позволяет получить содержимое body в формате ANSI-строки:
function GetInnerHTMLFromBody(const ADocument: IHTMLDOCUMENT2): AnsiString;
var
ms: TMemoryStream;
startBody, stopBody: integer;
const
bodyTag = '<BODY>';
closedBodyTag = '</BODY>';
begin
Result := '';
if ADocument <> nil then
begin
ms := TMemoryStream.Create;
try
if Succeeded((ADocument as IPersistStreamInit).Save(
TStreamAdapter.Create(ms, soReference) as IStream, True)) then
begin
ms.Seek(0, soFromBeginning);
SetLength(Result, ms.Size);
ms.ReadBuffer(Result[1], ms.Size);
// Поиск начала и конца тега body
startBody := AnsiPos(Result, bodyTag) + Length(bodyTag);
stopBody := AnsiPos(Result, closedBodyTag);
if startBody > Length(Result) then
stopBody := Length(Result)
else
stopBody := stopBody - 1;
// Выделение содержимого body
Result := Copy(Result, startBody, stopBody - startBody);
end;
finally
ms.Free;
end;
end;
end;
Если HTML-документ использует Unicode-encoding, потребуется дополнительное преобразование из Unicode в ANSI-строку.
Комментарии
В некоторых случаях, при использовании данного метода, в потоке может возвращаться только <HTML></HTML>. Это может быть связано с тем, что HTML-документ не был полностью загружен или использована функция PasteHTML, что не приводит к ожидаемому результату.
Вывод
Для корректного получения содержимого body в формате ANSI-строки в Delphi, можно использовать метод с IPersistStream, однако необходимо учитывать возможные особенности работы с Unicode-encoding и соответствующим образом преобразовывать данные.
Вопрос касается преобразования содержимого элемента body HTML-документа в строку ANSI-формат в среде Delphi, учитывая, что Unicode-символы не возвращаются в виде их строковых представлений, а уже преобразованы в Unicode-значения.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.