Исходный код HTML от TWebBrowser - Как определить кодировку потока?

На основании этого вопроса: Как получить исходный код HTML из TWebBrowser

Если я запускаю этот код со страницей html с кодовой страницей Unicode, результат будет тарабарщиной, потому что TStringStream не является Unicode в D7. . страница может иметь кодировку UTF8 или другую кодовую страницу (Ansi).

Как я могу определить, является ли TStream / IPersistStreamInit Unicode / UTF8 / Ansi?

Как мне всегда возвращать правильный результат в виде WideString для этой функции?

function GetWebBrowserHTML(const WebBrowser: TWebBrowser): WideString;

Если я заменю TStringStream на TMemoryStream и сохраню TMemoryStream в файл, все будет хорошо. Это может быть Unicode / UTF8 / Ansi. но я всегда хочу вернуть поток как WideString:

function GetWebBrowserHTML(const WebBrowser: TWebBrowser): WideString;
var
  // LStream: TStringStream;
  LStream: TMemoryStream;
  Stream : IStream;
  LPersistStreamInit : IPersistStreamInit;
begin
  if not Assigned(WebBrowser.Document) then exit;
  // LStream := TStringStream.Create('');
  LStream := TMemoryStream.Create;
  try
    LPersistStreamInit := WebBrowser.Document as IPersistStreamInit;
    Stream := TStreamAdapter.Create(LStream,soReference);
    LPersistStreamInit.Save(Stream,true);
    // result := LStream.DataString;
    LStream.SaveToFile('c:\test\test.txt'); // test only - file is ok
    Result := ??? // WideString
  finally
    LStream.Free();
  end;
end;

РЕДАКТИРОВАТЬ: Я нашел эту статью - Как загружать и сохранять документы в TWebBrowser в стиле Delphi путь

Что делает именно то, что мне нужно. но корректно работает только с компиляторами Delphi Unicode (D2009 +). прочтите раздел Заключение:

Очевидно, мы могли бы сделать гораздо больше. На ум сразу приходит пара вещей. Мы модернизируем некоторые функции Unicode и поддержку кодировок, отличных от ANSI, в код компилятора до Unicode. Настоящий код при компиляции с чем-либо ранее, чем Delphi 2009, не будет правильно сохранять содержимое документа в строки, если набор символов документа не является ANSI.

Магия явно находится в TEncoding классе (TEncoding.GetBufferEncoding). а у D7 нет TEncoding. Любые идеи?


person Vlad    schedule 10.01.2013    source источник
comment
Возможно, это поможет msdn.microsoft.com/en -us / library / jj160620 (v = vs.85) .aspx   -  person Sir Rufo    schedule 11.01.2013
comment
Попробуйте какой-нибудь StringList с поддержкой Unicode. В библиотеке jcl.sf.net есть TWideStringList и TJclWideStringList, а в компонентах TNT Unicode есть TWideStringList, и я думаю, что их гораздо больше. Возможно, у некоторых из них так или иначе есть адаптер COM IStringList. Попробуйте их или попробуйте найти больше реализаций Unicode StringList для Delphi 7, в Google, на torry.net или в каком-либо другом сборщике   -  person Arioch 'The    schedule 11.01.2013
comment
MSIE Внесены в DOM такие свойства, как .outerHTML и .innerHTML. Итак, я уверен, что вам нужно добраться до дерева HTML DOM, получить тег HTML, а затем получить его свойство externalHTML как BSTR, также известное как WideString, без промежуточных COM-объектов. Возможно, для этого вам понадобится немного JavaScript. Поисковые темы, например, как нажимать кнопку в TWebControl - они могут предоставить вам примеры, как найти какой-либо тег как объект JS со стороны Delphi и как вызвать его методы / свойства. Вам нужно будет прочитать свойство externalHTML для корневого тега HTML.   -  person Arioch 'The    schedule 11.01.2013


Ответы (1)


Я использовал GpTextStream для обработки преобразования (должно работать для всех версий Delphi):

function GetCodePageFromHTMLCharSet(Charset: WideString): Word;
const
  WIN_CHARSET = 'windows-';
  ISO_CHARSET = 'iso-';
var
  S: string;
begin
  Result := 0;
  if Charset = 'unicode' then
    Result := CP_UNICODE else
  if Charset = 'utf-8' then
    Result := CP_UTF8 else
  if Pos(WIN_CHARSET, Charset) <> 0 then
  begin
    S := Copy(Charset, Length(WIN_CHARSET) + 1, Maxint);
    Result := StrToIntDef(S, 0);
  end else
  if Pos(ISO_CHARSET, Charset) <> 0 then // ISO-8859 (e.g. iso-8859-1: => 28591)
  begin
    S := Copy(Charset, Length(ISO_CHARSET) + 1, Maxint);
    S := Copy(S, Pos('-', S) + 1, 2);
    if S = '15' then // ISO-8859-15 (Latin 9)
      Result := 28605
    else
      Result := StrToIntDef('2859' + S, 0);
  end;
end;

function GetWebBrowserHTML(WebBrowser: TWebBrowser): WideString;
var
  LStream: TMemoryStream;
  Stream: IStream;
  LPersistStreamInit: IPersistStreamInit;
  TextStream: TGpTextStream;
  Charset: WideString;
  Buf: WideString;
  CodePage: Word;
  N: Integer;
begin
  Result := ''; 
  if not Assigned(WebBrowser.Document) then Exit;
  LStream := TMemoryStream.Create;
  try
    LPersistStreamInit := WebBrowser.Document as IPersistStreamInit;
    Stream := TStreamAdapter.Create(LStream, soReference);
    if Failed(LPersistStreamInit.Save(Stream, True)) then Exit;
    Charset := (WebBrowser.Document as IHTMLDocument2).charset;
    CodePage := GetCodePageFromHTMLCharSet(Charset);
    N := LStream.Size;
    SetLength(Buf, N);
    TextStream := TGpTextStream.Create(LStream, tsaccRead, [], CodePage);
    try
      N := TextStream.Read(Buf[1], N * SizeOf(WideChar)) div SizeOf(WideChar);
      SetLength(Buf, N);
      Result := Buf;
    finally
      TextStream.Free;
    end;
  finally
    LStream.Free();
  end;
end;
person Vlad    schedule 13.01.2013