![]() |
IUnknown / XML-Link im TreeView
Hallo!
Ich habe vor einiger Zeit mit Eurer Hilfe (vor allem marabu hat mir sehr geholfen) eine Funktion ausgeknobelt, mit der man durch vergleichen der Zeiger herausfinden kann, welcher XML-Knoten zum entsprechenden Treeviewknoten gehört. Siehe auch: ![]() Die Funktion sieht wie folgt aus:
Delphi-Quellcode:
Das funktioniert soweit wunderbar. Leider kommte es aber sehr selten dazu, dass die Zeiger nicht mehr zueinander passen, obwohl (nachweislich) sowohl der XML-, als auch der Treeviewknoten noch vorhanden ist. Wenn die Baumansicht aktualisiert bzw. neu aufgebaut wird, stimmen die Zeiger wieder.
function FindTreeNodeXML(LinkedXMLNode:IXMLDOMNode):TTreeNode;
var cnt:integer; u_LinkedNode, u_chekNode : IUnknown; begin //Durch alle Knoten laufen for cnt:= 0 to form1.TrView_Struktur.Items.Count-1 do begin u_chekNode := PNodeState(form1.TrView_Struktur. Items[cnt].Data).XMLNode as IUnknown; u_LinkedNode := LinkedXMLNode as IUnknown; if u_chekNode = u_LinkedNode then begin result:=form1.TrView_Struktur.Items[cnt]; exit; end; end; result:=nil; end; Da ich zwar beim Vergleich das Elemtarinterface (IUnknown) verwende, aber zu den TreeView-Knoten einfach den Zeiger auf den XML-Knoten, ist meine Vermutung, dass dieses Problem durch eine Aktion des Betriebssystems hervorgerufen wird, die dafür sorgt, dass die Zeiger nicht mehr zueinander passen? Ist meine Theorie richtig? Wenn ich schonn beim Speichern des Zeigers im Treeview IUnknown verwenden würde, würde das das Problem lösen? Das Problem tritt sehr selten (meist nach langer Wartezeit) auf und ist dementsprechend schwer zu reproduzieren. Wenn es aber auftritt, so sind alle Zeiger, die im Treeview abgelegt wurden, betroffen. Hat jemand eine Idee hierzu? Was kann die Ursache sein? Gruß, StTüff |
Re: IUnknown / XML-Link im TreeView
Du darfst eigentlich nicht direkt die Interfacepointer vergleichen, sondern den XPath.
Ein XMLNode hat ja einen vollständigen Pfad (z.B.: /rss/chanel/item[3]/title) Wenn zwei Nodes den gleichen Pfad haben, dann sind sie gleich. |
Re: IUnknown / XML-Link im TreeView
Hallo Shmia!
Ich glaub das ist ein Missverständnis: Ich vergleiche keine 2 XML-Knoten miteinander. Vielleicht noch mal kurz der Hintergrund: Ich lese eine XML-Datei ein und stelle den Inhalt in einem Treeview dar. Damit ich später (beim Bearbeiten der Daten im TreeView) direkt auf die zugehörigen XML-Knoten zugreifen kann, lege ich beim Aufbau des Treeviews zu jedem TreeNode einen Zeiger auf den XML-Knoten ab. Das funktioniert sehr gut. Nun gibt es aber auch den ungedrehten Fall: Ich habe einen XML-Knoten und suche den zugehörigen Eintrag im TreeView. Auch das funktioniert mit der gezeigten Funktion sehr gut. Leider kommt es aber in sehr seltenen Fällen zur Fehlfunktion. Es ist nicht durch eine User-Aktion reproduzierbar und scheint zufällig aufzutreten. Deshalb mein Verdacht richtung Betriebssystem (ist übrigens XP Prof.). Gruß und vielen Dank für Deinen Beitrag, StTüff |
Re: IUnknown / XML-Link im TreeView
Hallo Shmia!
Ich glaube Du hattest es doch richtig verstanden. Bitte Entschuldige. Der Denkfehler liegt bei mir. Ich vermute Du wolltest damit sagen, dass ich den XPath des tatsächlichen Knotens mit den Knoten, die (bzw. deren Zeiger) im Treeview hinterlegt sind vergleichen soll. Habe ich das jetzt richtig wiedergegeben? Das ist theoretisch natürlich möglich. Da ich dann aber beim durchlaufen der Schleife für jeden Knoten im TreeView den XPath ermitteln müsste, ist das auch aufwendiger (zumindest rechenintensiver). Ich würde schon gerne bei der einfacheren Lösung bleiben, wenn sich nicht herausstellt, dass es hier grundsätzliche Dinge gibt, die dagegen sprechen. Da es die meiste Zeit funktioniert hoffe ich den Grund noch zu finden, warum es manchmal ohne das Zutun des Anwenders schief geht. Ich hoffe zusätzlich darauf, dass sich das Problem dann einfach beheben lässt. Momentan kenne ich aber noch nicht ein mal den Grund, warum es in so seltenen Fällen daneben geht. Gruß, StTüff |
Re: IUnknown / XML-Link im TreeView
Zitat:
Zitat:
Für MSXML könnte das so aussehen:
Delphi-Quellcode:
function GetFullNodePath(node:IXMLDOMNode):string;
var i : Integer; n : IXMLDOMNode; begin if node.nodeType=NODE_DOCUMENT then Result := '' else if Assigned(node.parentNode) then // rekursiver Aufruf Result := GetFullNodePath(node.parentNode)+'/'+node.nodeName else Result := node.nodeName; // Anzahl der Vorgänger mit gleichem Namen feststellen n := node.previousSibling; i := 1; while Assigned(n) do begin if (n.nodeName = node.nodeName) and (n.nodeType = NODE_ELEMENT) then Inc(i); n := n.previousSibling; end; if i > 1 then Result := Result + '['+IntToStr(i)+']'; end; Zitat:
Ein Knoten kann auch mit .cloneNode() kopiert werden. Auch wenn man über die Grenzen eines Threads (oder Appartment ?) geht, haben zwei Interfacepointer verschiedene Adressen. Würde den sourcecode mal so ändern:
Delphi-Quellcode:
So spart man sich eine Interfaceumwandlung.
u_chekNode := PNodeState(form1.TrView_Struktur.
Items[cnt].Data).XMLNode as IXMLDOMNode; if u_chekNode = LinkedXMLNode then Vielleicht sollte man die 2. Umwandlung auch einsparen und einen Cast-Operator nehmen:
Delphi-Quellcode:
Manchmal ist es so, dass man verschiedene Interfacepointer bekommt, je nach dem
u_chekNode := IXMLDOMNode(PNodeState(form1.TrView_Struktur.
Items[cnt].Data).XMLNode); if u_chekNode = LinkedXMLNode then in welcher Reihenfolge man die Interface umgewandelt. Das hat mit Aggregation und Containment zu tun und ist nicht einfach zu verstehen. |
Re: IUnknown / XML-Link im TreeView
Hallo Stephan,
deine Funktion würde bei mir aus verschiedenen Gründen so aussehen:
Delphi-Quellcode:
Allerdings würde ich diese Funktion nicht benötigen, da ich so beim Suchen jedesmal im Mittel n/2 Knoten betrachten müsste. Ich würde für die Suche einen sortierbaren Container einführen, in welchem per binary search der TreeNode zu einem XmlNode gefunden werden kann. Die Signatur ändert sich dann geringfügig, indem dieser Container als erstes Argument an die Funktion FindNode() übergeben wird.
function FindNode(nodes: TTreeNodes; data: Pointer): TTreeNode;
var i: Integer; begin Result := nil; for i := 0 to Pred(nodes.Count) do if nodes[i].Data = data then begin Result := nodes[i]; Break; end; end; Zu deinem Bericht über die sporadisch und scheinbar unmotivierten Zeigerverluste fällt mir nur eines ein: Eventuell wurden die Schnittstellenzeiger zwischenzeitlich freigegeben und wieder neu erzeugt. Um das sicher auszuschließen, sollte vor dem Einfügen in den Container der Reference Count des Interface erhöht und beim Entfernen wieder erniedrigt werden. Fehler in deinem Code schließen wir mal aus... Freundliche Grüße |
Re: IUnknown / XML-Link im TreeView
Hallo Shmia!
Dein Vorschlag für den alternativen Code entspricht meiner ursprünglichen Funktion und funktioniert nicht, da sich diese Pointer tatsächlich ändern. Die Lösung war damals die Verwendung von IUnknown (siehe ![]() In der XML-Struktur wird nichts verändert solange der Anwender nichts unternimmt. Da das Problem auch auftritt, wenn ich die Datei Lade und dann einfach für lange Zeit stehen lasse (die genaue Zeit konnte ich nicht ermitteln, scheint auch nicht konstant zu sein), kann ich ein Problem in meinem Code mit ziemlicher Sicherheit ausschließen (aber was ist schon sicher?). Inzwischen habe ich mir eine kleine Debughilfe in das Programm eingebaut, die Informationen zu den Knoten ausgibt. Ich hoffe so das Problem besser eingrenzen zu können (Ist aber schwer, da es so selten auftritt). Hallo Marabu! Ehrlich gesagt überfordertst Du mich im Moment noch ein wenig (ich hoffe, dass ich weiter lerne...). Ich möchte bezüglich der Suche momentan auch nichts optimieren, solange ich das Problem nicht genau kenne, zumal ich das durch die verwendung von Containern auch nicht löse, oder? Hört sich aber interesant an, hast Du mir einen Link zu einem ähnlichen Beispiel, bei dem ich das mal nachvollziehen kann? Dein Vorschlag mit dem Referenzcount: Bezieht sich der nur auf die "Containerlösung", oder kann ich das auch verwenden? Wie erhöht man den Referncount manuell? Bei der Suche habe ich auf die Schnelle nicht viel gefunden. Ich kann mir das ehrlich gesagt im Moment nicht richtig vorstellen, was da zu tun ist. Zitat:
Wenn das und die Aussage Zitat:
Gruß, Stüff |
Re: IUnknown / XML-Link im TreeView
..... wartet mal ich glaube ich habe etwas gefunden ... muss das mal genauer anschauen :coder: .
Wenn meine Vermutung stimmt, dann liegt es doch wieder an meinem Code :wall: . Melde mich wieder, wenn ich der Spur nachgegangen bin. Gruß, StTüff |
Re: IUnknown / XML-Link im TreeView
:oops: Oh Gott ist das peinlich!
Zitat:
Liebes Windows: Ich nehme alle Verdächtigungen zurück. Jetzt hätte ich Zeit, mich um eine optimierte Suche mit Containern zu kümmern. Gibt es da Tutorials, etwas in der Codelibrary oder im WWW dazu? Oder: Lohnt es sich hierfür einen neuen Thread aufzumachen? Gruß und vielen Dank an Euch! StTüff |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:47 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz