Форум: "Сети";
Текущий архив: 2002.05.20;
Скачать: [xml.tar.bz2];
Внизпреобразование документа 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;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.006 c