Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.05.20;
Скачать: CL | DM;

Вниз

преобразование документа HTML в XHTML   Найти похожие ветки 

 
plash07   (2002-03-05 15:36) [0]

Господа Мастера!
Нужно сделать преобразование документа HTML в XHTML.
Есть код на VB.

Dim ie As InternetExplorer, doc As MSHTML.HTMLDocument, url As String
" Создаем объект InternetExplorer
Set ie = New InternetExplorer
url = "file://" & inPath
" Открываем HTML-документ
ie.navigate url

" создаем объект HTML DOM
Set doc = ie.document
" Начинаем рекурсивный обход корня
OutputElement doc.documentElement, ""

.......

Private Sub OutputElement(el As Object, indent As String)
Dim c, i As Integer, s As String, a As Object, n As Object

.......
" просмотр дочерних элементов
For i = 0 To el.childNodes.length - 1

" Присваиваем n значение дочернего элемента
Set n = el.childNodes(i)

If n.nodeType = 1 Then
" дочерний элемент - HTML элемент
OutputElement n, indent & " "
Else
" дочерний элемент - текст
......
End If
Next
.....
End Sub

При первом входе в процедуру OutputElement переменная el представляет собой объект интерфейса HTMLHtmlElement, переменной n присваивается значение дочернего элемента – HTMLHeadDocument, и делается рекурсия на процедуру OutputElement.
При втором входе в процедуру OutputElement переменная el представляет собой объект интерфейса HTMLHeadDocument, переменной n присваивается значение дочернего элемента – HTMLTitleElement, и делается рекурсия на процедуру OutputElement. И т.д.

При переводе данного кода в Delphi столкнулся с проблемой следующего характера.
Как определить переменную el и n в процедуре OutputElement, если заранее известно, что будут использоваться различные интерфейсы?
Если можно – примеры.


 
kig   (2002-03-05 16:22) [1]

el As Object в VB равен

el : IDispatch в Дельфи

также можно
el : Variant


 
plash07   (2002-03-06 12:39) [2]

Никогда не работал с интерфейсами, поэтому много непонимания.
Определяю el как IDispatch:

Procedure OutputElement(el: IDispatch ; indent : String);
Var
...
ret : IHTMLDOMChildrenCollection;
n : IDispatch;
begin
...
// В этом месте выдается ошибка об отсутствии данного метода
ret := el.childNodes as IHTMLDOMChildrenCollection;
...
// Просмотр дочерних элементов
For i:=0 To ret.length-1 do
Begin
n := ret.item(i) as IDispatch;
If n.nodeType=1 then
begin
OutputElement(n,indent + " ");
end Else
begin
...
end;
end;
...
end;

В литературе говорится, что для интерфейса IDispatch нужно использовать позднее связование с помощью Invoke().
Но как это сделать, поподробнее?


 
plash07   (2002-03-07 11:09) [3]

Ответ от kig:
>// В этом месте выдается ошибка об отсутствии данного метода
ret := el.childNodes as IHTMLDOMChildrenCollection;

В этом случае необходимо сначала запросить интерфейс IHTMLDOMChildrenCollection.
Делается это через метод QueryInterface интерфейса IUnknown (IDispatch наследуется от него).
Если Вам нет времени копаться в этих проблемах (это вообще-то не Дельфи, а основы COM), используйте вместо IDispatch Varaint при передаче разных объектов в Вашу процедуру. В этом случае в приведенном примере ошибки быть не должно, а Дельфи сама сгенерит необходимый код для Invoke.


 
plash07   (2002-03-07 11:11) [4]

Определяю el как Variant. Выдается ошибка -

Procedure OutputElement(el: Variant ; indent : String);
Var
...
ret : IHTMLDOMChildrenCollection;
n : Variant;
begin
...
// В этом месте выдается ошибка “Operator not applicable to this operand type“
ret := el.childNodes as IHTMLDOMChildrenCollection;
...
// Просмотр дочерних элементов
For i:=0 To ret.length-1 do
Begin
n := ret.item(i) as Variant;
If n.nodeType=1 then
begin
OutputElement(n,indent + " ");
end Else
begin
...
end;
end;
...
end;



>В этом случае необходимо сначала запросить интерфейс IHTMLDOMChildrenCollection.

>Делается это через метод QueryInterface интерфейса IUnknown (IDispatch наследуется от него).

Честно говоря, я только начал разбираться в основах COM, очень много вопросов.

Если несложно, не могли бы Вы продемонстрировать, как производится запрос интерфейса IHTMLDOMChildrenCollection через метод QueryInterface.



 
plash07   (2002-03-07 11:14) [5]

Совсем Вам чуть соврал))) (Привык к сям)

Что для IDispatch, что для Variant с ним (Varaint умеет его хранить), Д сама генерит код для запроса интерфейса
при такой конструкции

var im: IMyInteface;
idp: IDispatch;

im := idp as IMyInteface;

Т.е. в этом случае Д ведет себя точно также, как и VB. Отличие только в том, что надо явно указывать преобразования из интерфейса в интерфес (as)

Генерит она следующее

var hr: HRESULT;

hr := idp.QueryInterface(GUID IMyInteface, im); Здесь указатель на im - не помню как в Д
проверка hr = 0
idp.AddRef;

Примерно так....


Вот примерчик, я попробывал - работает.


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, OleCtrls, MSHTML_TLB, SHDocVw;

type
TForm1 = class(TForm)
Button1: TButton;
WebBrowser1: TWebBrowser;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
Procedure OutputElement(el: IHTMLDOMNode; indent : String);
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

Procedure TForm1.OutputElement(el: IHTMLDOMNode; indent : String);
Var
ret : IHTMLDOMChildrenCollection;
i : Integer;
begin
if (el.nodeType = DWORD(1)) then
begin
Memo1.Lines.Add(el.nodeName);
ret := el.childNodes as IHTMLDOMChildrenCollection;
For i:=0 To ret.length-1 do
OutputElement(ret.Item(i) as IHTMLDOMNode, "");
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
doc: IHTMLDocument3;
begin
WebBrowser1.Navigate(" http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1015331764&n=4");
while (WebBrowser1.ReadyState <> READYSTATE_COMPLETE) do
begin
Application.ProcessMessages;
end;
doc := WebBrowser1.Document as IHTMLDocument3;
OutputElement(doc.documentElement as IHTMLDOMNode, "");
end;

end.


 
plash07   (2002-03-07 12:06) [6]

> Т.е. в этом случае Д ведет себя точно также, как и VB. Отличие только в том, что надо явно указывать преобразования из интерфейса в интерфейс (as)

Скажите, я правильно понял, что конструкция из VB

Dim c, i As Integer, s As String, a As Object, n As Object

" просмотр дочерних элементов
For i = 0 To el.childNodes.length - 1

" Присваиваем n значение дочернего элемента
Set n = el.childNodes(i)

If n.nodeType = 1 Then
" дочерний элемент - HTML элемент
OutputElement n, indent & " "
Else
" дочерний элемент - текст
......
End If
Next

, где n сначала присваивается DispHTMLHeadDocument, при втором проходе DispHTMLTitleElement, далее DispHTMLMetaElement и т.д.,

в Delphi работать не будет, потому что нужно явно указывать преобразование из интерфейса в интерфейс?



По поводу кода – спасибо.

Но есть вопросик.

С интерфейсом IHTMLDOMNode у меня все работало еще до подачи вопроса в форум.

Проблема в том, что мне нужно использовать еще несколько интерфейсов, например IHTMLDOMAttribute для просмотра атрибутов и выставления нужных.


Procedure TForm1.OutputElement(el: IHTMLDOMNode; indent : String);
Var
ret : IHTMLDOMChildrenCollection;

a : IHTMLDOMAttribute;
i : Integer;
begin

// Здесь выдается ошибка “Interface not supported”
a := el.attributes as IHTMLDOMAttribute;

if (el.nodeType = DWORD(1)) then
begin
Memo1.Lines.Add(el.nodeName);
ret := el.childNodes as IHTMLDOMChildrenCollection;
For i:=0 To ret.length-1 do

OutputElement(ret.Item(i) as IHTMLDOMNode, "");
end;
end;


Я пробовал использовать вместо интерфейса IHTMLDOMNode интерфейсы которые должны использоваться по коду VB (DispHTMLHeadDocument, DispHTMLTitleElement, DispHTMLMetaElement, …), все работает, но в рекурсию войти не могу, потому что не знаю заранее какой интерфейс для el будет передан в процедуру OutputElement?




Страницы: 1 вся ветка

Текущий архив: 2002.05.20;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.01 c
1-64635
Dyacha
2002-05-08 12:46
2002.05.20
как можно реализовать печать книжкой


3-64554
Vov
2002-04-24 09:56
2002.05.20
Как на клиенте ловить сообщения об update таблицы


7-64854
davile
2002-02-20 19:23
2002.05.20
Kak узнать ID процесса?


6-64753
amg
2002-03-07 04:00
2002.05.20
Разделение данных на пакеты


7-64856
Andrewv
2001-12-13 14:21
2002.05.20
Работа с Win98