Hi,
die Frage zu
COM Collections kam inzwischen schon öfters, also möchte ich an dieser Stelle mal zeigen, wie mal in Delphi folgenden Visual Basic - Konstrukt umsetzt.
Code:
[b]dim[/b] Doc, Nodes, Node
[b]set[/b] Doc = Server.CreateObject("Msxml2.DOMDocument.4.0")
Doc.load("C:\Temp\hallo.xml")
[b]set[/b] Nodes = Doc.selectNodes(".//*")
[b]for each[/b] Node [b]in[/b] Nodes
ListBox1.Items.Add(Node.nodeName)
[b]next[/b]
Nun ist leider VB (bzw. VBScript) die einzige Sprache, welche dieses Konstrukt so unterstüzt. Damit dieses Konstrukt jedoch funktioniert, muss das
COM Objekt das
IEnumVariant Interface mittels der Methode
_newEnum exportieren. Über diese Methode und dieses Interface kann man diese Collection auch in anderen Programmiersprachen ansteuern. Nun das ersehnte Delphi-Beispiel zu obigem Beispiel.
Delphi-Quellcode:
var
// MSXML typische Interfaces
// Das Basis Dokument
Doc: IXMLDOMDocument2;
// Die COM Collection
Nodes: IXMLDOMNodeList;
// Das COM Collection Objekt
Node: IXMLDOMNode;
// das Interface zum Collection-Container
Enum: IEnumVariant;
// Anzahl der zurückgelieferten Elemente
Fetched: Cardinal;
// Der Empfänger des Collection-Objektes
ResultItem: OleVariant;
begin
// okay, einfach mal den XML DOM initialisieren
Doc := CoDOMDocument40.Create;
// XML file laden
Doc.load('
C:\Temp\hallo.xml');
// und eine Liste von aller (x) Nodes erzeugen
Nodes := Doc.selectNodes('
.//*');
// die Collection zurückgeben lassen
Enum := Nodes._newEnum
as IEnumVariant;
// die Collection reseten (ist theoretisch beim ersten Durchlauf nicht nötig
// sollte imho aber gemacht werden
Enum.Reset;
// das erste Element ermitteln
// der erste Parameter gibt an, wie viele Objekte zurückgeliefert werden
// sollen
// der zweite Parameter nimmt das Zielobjekt auf
// für diesen kann auch ein SafeArray von OleVariants übergeben werden
// der dritte Parameter gibt an, wieviele Objekte zurückgeliefert wurden
//
// die Übergabe von "1" für den ersten Parameter entspricht dem VB Konstrukt
// for each Item in Collection
Enum.Next(1, ResultItem, Fetched);
// Fetched muß also "1" sein, solange ein Element gefunden wird
while Fetched = 1
do
begin
// jetzt auf das gewünschte Interface casten - dazu als erstes das IDispatch
// Interface ermitteln und dann das Ziel-Interface
Node := IDispatch(ResultItem)
as IXMLDOMNode;
// und nun wie gewohnt arbeiten...
ListBox1.Items.Add(Node.nodeName);
// das nächste Element ermitteln und weiter im Job...
Enum.Next(1, ResultItem, Fetched);
end;
// jetzt noch die Collection freigeben - oder einfach weglassen, dann tut
// Delphi dieses spätestens beim Verlassen der Prozedur
Enum :=
nil;
end;
...
...