Einzelnen Beitrag anzeigen

Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 

COM Collections durchlaufen (_NewEnum, IEnumVariant)

  Alt 4. Nov 2003, 08:27
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;
......
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat