惭愧啊,基本功还不行;关于Interface 的Implements;具体例子是使用XML中SAX来输出Xml文档;(100分)

  • 主题发起人 主题发起人 蚊子
  • 开始时间 开始时间

蚊子

Unregistered / Unconfirmed
GUEST, unregistred user!

问题有点长,请耐心看完;
在MSXML 4.0 SDK中看到一个使用SAX入门例子,是VB写的。介绍如何使用XML的SAX(Simple API for XML)
http://msdn.microsoft.com/xml/articles/vbsax2jumpstart.exe

使用了XML中SAXXMLReader来读入Xml文档,实现了自己IVBSAXContentHandler和IVBSAXErrorHandler接口;
以下是有关文档;
SAXXMLReader
Coclass that implements the ISAXXMLReader interface. SAXXMLReader consumes the XML and throws
events to the handlers that you set for the reader. This example creates an instance of
SAXXMLReader, and then sets a ContentHandler and an ErrorHandler for receiving events from
the reader.

IVBSAXContentHandler
Catches events thrown by the reader. For this application, the ContentHandlerImpl class
implements the IVBSAXContentHandler interface. This application highlights the main events
received by the ContentHandler, including startDocument, endDocument, startElement, endElement,
and characters.

IVBSAXErrorHandler
Catches any errors raised during the read process. For this application, the ContentHandlerImpl
class also implements the IVBSAXErrorHandler interface. At this time, MSXML supports the
fatalError method only.


ContentHandlerImp.cls主要是实现了用户自己的IVBSAXContentHandler接口类,实现(重载?)接口的方法;
内容

Implements IVBSAXContentHandler

Private Sub IVBSAXContentHandler_startElement _
(strNamespaceURI As String, _
strLocalName As String, _
strQName As String, _
ByVal attributes As MSXML2.IVBSAXAttributes)

Dim i As Integer

Form1.Text2.text = Form1.Text2.text &amp
"<" &amp
strLocalName

For i = 0 To (attributes.length - 1)
Form1.Text2.text = Form1.Text2.text &amp
" " &amp
_
attributes.getLocalName(i) &amp
"=""" &amp
_
attributes.getValue(i) &amp
""""
Next

Form1.Text2.text = Form1.Text2.text &amp
">"

If strLocalName = "qu" Then
Err.Raise vbObjectError + 1, "ContentHandler.startElement", _
"Found element <qu>"
End If

End Sub

Private Sub IVBSAXContentHandler_endElement(strNamespaceURI As String, _
strLocalName As String, _
strQName As String)

Form1.Text2.text = Form1.Text2.text &amp
"</" &amp
strLocalName &amp
">"

End Sub

Private Sub IVBSAXContentHandler_characters(text As String)
text = Replace(text, vbLf, vbCrLf)
Form1.Text2.text = Form1.Text2.text &amp
text

End Sub

Private Property Set IVBSAXContentHandler_documentLocator(ByVal RHS As _
MSXML2.IVBSAXLocator)

End Property

Private Sub IVBSAXContentHandler_endDocument()

End Sub

Private Sub IVBSAXContentHandler_endPrefixMapping(strPrefix As String)

End Sub

Private Sub IVBSAXContentHandler_ignorableWhitespace(strChars As String)

End Sub

Private Sub IVBSAXContentHandler_processingInstruction(target As String, _
data As String)

Form1.Text2.text = Form1.Text2.text &amp
"<?" &amp
target &amp
" " _
&amp
data &amp
">"

End Sub

Private Sub IVBSAXContentHandler_skippedEntity(strName As String)

End Sub

Private Sub IVBSAXContentHandler_startDocument()

End Sub

Private Sub IVBSAXContentHandler_startPrefixMapping(strPrefix As String, _
strURI As String)

End Sub

在Form中的button click事件是这样的;
Private Sub Command1_Click()

Dim reader As New SAXXMLReader 'Reads the XML document
Dim contentHandler As New ContentHandlerImpl 'Receives parsing events
Dim errorHandler As New ErrorHandlerImpl 'Receive error events
Text2.text = ""
Set reader.contentHandler = contentHandler 'They work together
Set reader.errorHandler = errorHandler 'They also work together
On Error GoTo 10
reader.parseURL (Text1.text) 'Parse the document
'结果会输出到text2中
Exit Sub 'That's all, folks!

10: Text2.text = Text2.text &amp
"*** Error *** " &amp
Err.Number _
&amp
" : " &amp
Err.Description
End Sub


我现在要把这个例子翻译成Delphi,主Form很esay,但是翻译VB的类模块时就不知道怎么处理了。

Implements IVBSAXContentHandler
-------------------------------- >这句不懂怎么翻译到Delphi中;

我已经在Delphi中Import了Msxml.dll进来,在MSXML2_TLB.pas中;IVBSAXContentHandler是这样定义的;
IVBSAXContentHandler = interface(IDispatch)
['{2ED7290A-4DD5-4B46-BB26-4E4155E77FAA}']
procedure Set_documentLocator(const Param1: IVBSAXLocator)
safecall;
procedure startDocument
safecall;
procedure endDocument
safecall;
procedure startPrefixMapping(var strPrefix: WideString
var strURI: WideString)
safecall;
procedure endPrefixMapping(var strPrefix: WideString)
safecall;
procedure startElement(var strNamespaceURI: WideString
var strLocalName: WideString

var strQName: WideString
const oAttributes: IVBSAXAttributes)
safecall;
procedure endElement(var strNamespaceURI: WideString
var strLocalName: WideString

var strQName: WideString)
safecall;
procedure characters(var strChars: WideString)
safecall;
procedure ignorableWhitespace(var strChars: WideString)
safecall;
procedure processingInstruction(var strTarget: WideString
var strData: WideString)
safecall;
procedure skippedEntity(var strName: WideString)
safecall;
property documentLocator: IVBSAXLocator write Set_documentLocator;
end;

我想做的就是用自己的处理过程实现(重载?)这个接口中
procedure startElement(var strNamespaceURI: WideString
var strLocalName: WideString

var strQName: WideString
const oAttributes: IVBSAXAttributes)
safecall;
procedure endElement(var strNamespaceURI: WideString
var strLocalName: WideString

var strQName: WideString)
safecall;
procedure processingInstruction(var strTarget: WideString
var strData: WideString)
safecall;

大致程序如下;
unit Unit2;

interface

uses
Classes,MSXML2_TLB,unit1;
type
MySAXContentHandle = class
procedure startElement(var strNamespaceURI: WideString
var strLocalName: WideString;
var strQName: WideString
const oAttributes: IVBSAXAttributes)
safecall;
procedure endElement(var strNamespaceURI: WideString
var strLocalName: WideString;
var strQName: WideString)
safecall;
procedure processingInstruction(var strTarget: WideString
var strData: WideString)
safecall;
end;


NewSAXContentHandle = class(TInterfacedObject,IVBSAXContentHandler)
FMySAXContentHandle:MySAXContentHandle;
property ContentHandle: MySAXContentHandle read FMySAXContentHandle implements IVBSAXContentHandler;
end;
implementation
procedure MySAXContentHandle.startElement(var strNamespaceURI: WideString
var strLocalName: WideString;
var strQName: WideString
const oAttributes: IVBSAXAttributes)
safecall;
var i:integer;
s:WideString;
begin
s:='<' + strLocalName;
for i:=0 to oAttributes.length-1 do
begin
s:=s + ' '+ oAttributes.getLocalName(i)+'="'+oAttributes.getValue(i)+'"';
end;
s:=s+'>';
form1.memo1.lines.add(s);
end;

procedure MySAXContentHandle.endElement(var strNamespaceURI: WideString
var strLocalName: WideString;
var strQName: WideString)
safecall;
begin
form1.memo1.lines.add('</'+strLocalName+'>');
end;
procedure MySAXContentHandle.processingInstruction(var strTarget: WideString
var strData: WideString)
safecall;
begin
form1.memo1.lines.add('<?'+strTarget+' '+strData+'>');
end;
end.

编译通不过;很多 Undeclared identifier:
甚至连Invoke,GetIDsOfName,等都说没有;

关键再于在VB中 使用
Implements IVBSAXContentHandler

就可以对IVBSAXContentHandler的所有过程都重新实现一次;
在Delphi中不知道如何实现这个Implements?
 
建议这样试试看:NewSAXContentHandle = class(MySAXContentHandle, TInterfacedObject,IVBSAXContentHandler)
 
孙老师:
NewSAXContentHandle = class(MySAXContentHandle, TInterfacedObject,IVBSAXContentHandler)
^第二个参数要求一定要是Interface,不能是类啊
 
我至今为止.只提过两个问题;能得到答案的百分比是 0%!!
好失望!!
 
不要着急,我记着您的问题呢。网上有这方面的资料,
http://www.delphizine.com/features/2000/03/di200003kw_f/di200003kw_f.asp
http://www.delphizine.com/download/default.asp?page=5&amp;sort=D&amp;ord=D
但是这个网站是收费的,我正在找同事中谁注册过。
 
Delphi 中 “Implements”接口的方法一般是:

创建一个 Automaction Object,取名为 Test
File | New ... -> ActiveX - Automation Object
系统会帮您生成: TTest = class(TAutoObject, ITest)
您手工加入接口: TTest = class(TAutoObject, ITest, IVBSAXContentHandler)
然后实现接口一个借口函数的方法是:

TTest = class(TAutoObject, ITest, IVBSAXContentHandler)
procedure IVBSAXContentHandler.startElement = startElement;
procedure startElement(...)
safecall;
...
end;

procedure TTest.startElement(...);
begin
end;

以上是 startElement,您必须实现 startElement。您必须实现接口中的所有方法:
象 set_document_Locator,endPrefixMapping ... 等等共11个。

您试验一下看。上一个贴子所提到的那份资料还没有 down 到。
 
BINGO!!
谢谢孙老师,这个例子我写好调试通过了.例子虽然没什么意义,但对SAX的调用也算有了一定的认识,
还有就是对接口类的实现也有一定的认识了.

但是我还想请教孙老师,有关Interface类的实现问题,我知道TInfacedObject实现了IUnknown接口的
方法,QueryInterface,_Addref,_release;但对于IDispatch有那个基本的类实现了他的方法呢,
比如Invoke,GetIDsOfName,等等,这些方法大致有什么用途,(invoke好象给不支持指针的言语提供的
接口)..
还有Interface这个概念能不能讲讲啊,难道接口里的方法只是声明了他里面的调用,而没有真正实现
其调用?

 
附上改写的例子,里面还是有不明白的地方;

1)主Form Unit1.pas

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, OleServer, MSXML2_TLB, ExtCtrls;

type
TForm1 = class(TForm)
Memo1: TMemo;
Panel1: TPanel;
Button1: TButton;
Edit1: TEdit;
SAXXMLReader1: TSAXXMLReader;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation
uses unit3;
{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var ContentH:TMySAXContentHandle;
begin
ContentH:=TMySAXContentHandle.create();
SAXXMLReader1.contentHandler:=ContentH;
SAXXMLReader1.parseURL(Edit1.text);
ContentH.Destroy;
end;

end.

2)引入的AutoOject类和接口声明,Project1_TLB.pas
unit Project1_TLB;

// ************************************************************************ //
// WARNING
// -------
// The types declared in this file were generated from data read from a
// Type Library. If this type library is explicitly or indirectly (via
// another type library referring to this type library) re-imported, or the
// 'Refresh' command of the Type Library Editor activated while editing the
// Type Library, the contents of this file will be regenerated and all
// manual modifications will be lost.
// ************************************************************************ //

// PASTLWTR : $Revision: 1.88.1.0.1.0 $
// File generated on 2001-6-5 22:43:20 from Type Library described below.

// ************************************************************************ //
// Type Lib: I:/编程资料/Xml专题/MSXML 4.0 SDK 学习例子/XMLSAX/Project1.tlb (1)
// IID/LCID: {56958F9C-165B-4E3F-A424-6701EED230E3}/0
// Helpfile:
// DepndLst:
// (1) v2.0 stdole, (C:/WINNT/System32/stdole2.tlb)
// (2) v4.0 StdVCL, (C:/WINNT/System32/STDVCL40.DLL)
// ************************************************************************ //
{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers.
interface

uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL;

// *********************************************************************//
// GUIDS declared in the TypeLibrary. Following prefixes are used:
// Type Libraries : LIBID_xxxx
// CoClasses : CLASS_xxxx
// DISPInterfaces : DIID_xxxx
// Non-DISP interfaces: IID_xxxx
// *********************************************************************//
const
// TypeLibrary Major and minor versions
Project1MajorVersion = 1;
Project1MinorVersion = 0;

LIBID_Project1: TGUID = '{56958F9C-165B-4E3F-A424-6701EED230E3}';

IID_IMySAXContentHandle: TGUID = '{53DC02E9-2F0F-4D3B-A943-C9F5A94C0CC8}';
CLASS_MySAXContentHandle: TGUID = '{1BB9C05F-30EC-4954-B7EF-7C35E878BD7A}';
type

// *********************************************************************//
// Forward declaration of types defined in TypeLibrary
// *********************************************************************//
IMySAXContentHandle = interface;
IMySAXContentHandleDisp = dispinterface;

// *********************************************************************//
// Declaration of CoClasses defined in Type Library
// (NOTE: Here we map each CoClass to its Default Interface)
// *********************************************************************//
MySAXContentHandle = IMySAXContentHandle;


// *********************************************************************//
// Interface: IMySAXContentHandle
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {53DC02E9-2F0F-4D3B-A943-C9F5A94C0CC8}
// *********************************************************************//
IMySAXContentHandle = interface(IDispatch)
['{53DC02E9-2F0F-4D3B-A943-C9F5A94C0CC8}']
end;

// *********************************************************************//
// DispIntf: IMySAXContentHandleDisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {53DC02E9-2F0F-4D3B-A943-C9F5A94C0CC8}
// *********************************************************************//
IMySAXContentHandleDisp = dispinterface
['{53DC02E9-2F0F-4D3B-A943-C9F5A94C0CC8}']
end;

// *********************************************************************//
// The Class CoMySAXContentHandle provides a Create and CreateRemote method to
// create instances of the default interface IMySAXContentHandle exposed by
// the CoClass MySAXContentHandle. The functions are intended to be used by
// clients wishing to automate the CoClass objects exposed by the
// server of this typelibrary.
// *********************************************************************//
CoMySAXContentHandle = class
class function Create: IMySAXContentHandle;
class function CreateRemote(const MachineName: string): IMySAXContentHandle;
end;

implementation

uses ComObj;

class function CoMySAXContentHandle.Create: IMySAXContentHandle;
begin
Result := CreateComObject(CLASS_MySAXContentHandle) as IMySAXContentHandle;
end;

class function CoMySAXContentHandle.CreateRemote(const MachineName: string): IMySAXContentHandle;
begin
Result := CreateRemoteComObject(MachineName, CLASS_MySAXContentHandle) as IMySAXContentHandle;
end;
end.

3)接口类的实现:unit3.pas

unit Unit3;

interface
uses
ComObj, ActiveX, Project1_TLB, MSXML2_TLB,StdVcl;

type
TMySAXContentHandle = class(TAutoObject, IMySAXContentHandle,IVBSAXContentHandler)
protected
procedure IVBSAXContentHandler.Set_documentLocator = Set_documentLocator;
procedure IVBSAXContentHandler.startDocument = startDocument;
procedure IVBSAXContentHandler.endDocument = endDocument;
procedure IVBSAXContentHandler.startElement = startElement;
procedure IVBSAXContentHandler.endElement = endElement;
procedure IVBSAXContentHandler.startPrefixMapping = startPrefixMapping;
procedure IVBSAXContentHandler.endPrefixMapping = endPrefixMapping;
procedure IVBSAXContentHandler.characters = characters;
procedure IVBSAXContentHandler.ignorableWhitespace = ignorableWhitespace;
procedure IVBSAXContentHandler.processingInstruction = processingInstruction;
procedure IVBSAXContentHandler.skippedEntity = skippedEntity;
procedure Set_documentLocator(const Param1: IVBSAXLocator)
safecall;
procedure startDocument
safecall;
procedure endDocument
safecall;
procedure startPrefixMapping(var strPrefix: WideString
var strURI: WideString)
safecall;
procedure endPrefixMapping(var strPrefix: WideString)
safecall;
procedure startElement(var strNamespaceURI: WideString
var strLocalName: WideString;
var strQName: WideString
const oAttributes: IVBSAXAttributes)
safecall;
procedure endElement(var strNamespaceURI: WideString
var strLocalName: WideString;
var strQName: WideString)
safecall;
procedure characters(var strChars: WideString)
safecall;
procedure ignorableWhitespace(var strChars: WideString)
safecall;
procedure processingInstruction(var strTarget: WideString
var strData: WideString)
safecall;
procedure skippedEntity(var strName: WideString)
safecall;
property documentLocator: IVBSAXLocator write Set_documentLocator
{ Protected declarations }
end;

implementation

uses ComServ,unit1;
procedure TMySAXContentHandle.startElement(var strNamespaceURI: WideString
var strLocalName: WideString;
var strQName: WideString
const oAttributes: IVBSAXAttributes)
safecall;
var i:integer;
s:WideString;
begin
s:='<' + strLocalName;
for i:=0 to oAttributes.length-1 do
begin
s:=s + ' '+ oAttributes.getLocalName(i)+'="'+oAttributes.getValue(i)+'"';
end;
s:=s+'>';
form1.memo1.lines.add(s);
end;

procedure TMySAXContentHandle.endElement(var strNamespaceURI: WideString
var strLocalName: WideString;
var strQName: WideString)
safecall;
begin
form1.memo1.lines.add('</'+strLocalName+'>');
end;
procedure TMySAXContentHandle.processingInstruction(var strTarget: WideString
var strData: WideString)
safecall;
begin
form1.memo1.lines.add('<?'+strTarget+' '+strData+'>');
end;
procedure TMySAXContentHandle.Set_documentLocator(const Param1: IVBSAXLocator)
safecall;
begin
end;
procedure TMySAXContentHandle.startDocument
safecall;
begin
end;
procedure TMySAXContentHandle.endDocument
safecall;
begin
end;
procedure TMySAXContentHandle.startPrefixMapping(var strPrefix: WideString
var strURI: WideString)
safecall;
begin
end;
procedure TMySAXContentHandle.endPrefixMapping(var strPrefix: WideString)
safecall;
begin
end;
procedure TMySAXContentHandle.characters(var strChars: WideString)
safecall;
begin
end;
procedure TMySAXContentHandle.ignorableWhitespace(var strChars: WideString)
safecall;
begin
end;
procedure TMySAXContentHandle.skippedEntity(var strName: WideString)
safecall;
begin
end;

initialization
TAutoObjectFactory.Create(ComServer, TMySAXContentHandle, Class_MySAXContentHandle,
ciSingleInstance, tmApartment);
end.

疑问1.那么多空函数,编译的时候,不会给优化掉了?
疑问2.
procedure IVBSAXContentHandler.Set_documentLocator = Set_documentLocator;
这11个行,是不是相当于 把Interface IVBSAXContentHandler 的各个方法和函数 都一一替换(
或者实现),,
 
[:D]哈哈,我也遇到相同的问题了,幸好有好人 yysun和蚊子,只不过我用了msxml4.0,接口是
isaxcontenthandler,差不多啦. 真高兴! ^_^
 
后退
顶部