Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 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.011 c
3-64560
Мишган
2002-04-24 15:27
2002.05.20
dbiRegenIndexes


7-64844
Shiza
2002-02-18 19:17
2002.05.20
Доступ к прерываниям из дельфи


4-64873
matthew_v
2002-03-18 13:01
2002.05.20
Чтение и разбор spool-файла.


3-64482
DL
2002-04-22 18:19
2002.05.20
BD


3-64489
Filippov Stas
2002-04-21 00:27
2002.05.20
Функции в SQL.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский