Einzelnen Beitrag anzeigen

Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#252

AW: himXML (gesprochen himix ML)

  Alt 10. Okt 2010, 22:28
Ahhh, mir wurde einiges klarer jetzt! Danke!

Nachdem ich mir dann mal genau aufgemalt habe was da wo hin gepointert wird, ist mir aufgefallen, dass Node.InnerPrev und Node.InnerPrev.InnerNext noch fehlen.
Ich habe zudem nach wie vor bei schon einmal verschobenen Nodes den Fehler bekommen, dass die Node nicht in der Liste sei. Node.SetParent(self) hat Abhilfe geschaffen

Hier mal meine Anpassungen:
Delphi-Quellcode:
      Function TXMLNodeList.Insert(Node, RNode: TXMLNode; previousR: Boolean = False): TXMLNode;
      var
        tmp: TXMLNode;
      Begin
        If not (Node is TXMLNode) Then
          Raise EXMLException.Create(ClassType, 'Insert', @SInvalidNode);
        If (Assigned(_Parent) and (_Parent.InnerText <> '')) or (Assigned(_FirstNode)
            and ((_FirstNode.NodeType = xtCData) or (Node.NodeType = xtCData))) Then
          Raise EXMLException.Create(ClassType, 'Insert', @SIsTextNode, _Parent.Name);
        If Assigned(RNode) and (not (RNode is TXMLNode) or (RNode.ParentList <> Self)) Then
          Raise EXMLException.Create(ClassType, 'Insert', @SNodeNotInList);
        If Assigned(Node.ParentList) Then Node := Node.ParentList.Remove(Node);
        Inc(_NodesCount);
        If previousR Then Begin
          If not Assigned(RNode) Then RNode := _FirstNode;

          If not Assigned(_FirstNode) or (_FirstNode = RNode) Then _FirstNode := Node;
          If not Assigned(_LastNode) Then _LastNode := Node;
          If Assigned(RNode) Then Begin
            If Assigned(RNode.InnerPrev) Then RNode.InnerPrev.InnerNext := Node;
            Node.InnerPrev := RNode.InnerPrev;
            Node.InnerNext := RNode;
            RNode.InnerPrev := Node;
          End;
        End Else Begin
          If not Assigned(RNode) Then RNode := _LastNode;

          If not Assigned(_FirstNode) Then _FirstNode := Node;
          If not Assigned(_LastNode) or (_FirstNode = RNode) Then _LastNode := Node;
          If Assigned(RNode) Then Begin
            If Assigned(RNode.InnerNext) Then RNode.InnerNext.InnerPrev := Node;
            Node.InnerNext := RNode.InnerNext;
            tmp := Node.InnerPrev;
            Node.InnerPrev := RNode;
            RNode.InnerNext := Node;
            RNode.InnerPrev := tmp;
            if Assigned(tmp) then
              tmp.InnerNext := RNode;
            Node.SetParent(self);
            RNode.SetParent(self);
          End;
        End;
        Node.CheckCrypted(True);
        Result := Node;
        DoNodeChange(Result, xcAddetNode);
      End;
Ich habe nur den Zweig für previousR=false geändert, da die andere Variante bei benachbarten Nodes sehr lustige Verknotungen erzeugt (Node.InnerPrev zeigt wieder auf Node und so Dinge), und ich es nicht zwingend brauche. (Nach oben schieben lässt sich ja auch über runter schubsen des vorigen Nodes erreichen.)

Damit komme ich nun weiter, merci!!

Edit: Ach shit
Noch immer verschwinden RNodes, und zwar sobald das Node (also das direkt davor) vorher schon mal an einer Verschiebung beteiligt war. Ich habe jetzt 3 Seiten mit Pfeilen vollgekritzelt, und komme immer zu dem Ergebnis, dass diese Abfolge von Verbiegungen stimmen sollte:
Delphi-Quellcode:
            If Assigned(RNode.InnerNext) Then RNode.InnerNext.InnerPrev := Node;
            If Assigned(Node.InnerPrev) Then Node.InnerPrev.InnerNext := RNode;
            Node.InnerNext := RNode.InnerNext;
            RNode.InnerPrev := Node.InnerPrev;
            Node.InnerPrev := RNode;
            RNode.InnerNext := Node;
(Habe das "tmp" von oben eliminieren können, daher nochmals anders.)
Ich verzweifel langsam :\

Edit2
Das RNode verliert seinen Prev! Und zwar obwohl das Prev vom Node gültig ist. Aber WARUM!?
Wenn doch nur dieser sch**** Debugger in die Methode springen würde, WAHH! Auch DCU killen half nicht. Sowas liebe ich ja.

Edit3
Durch das vorige Remove von Node aus Node.ParentList werden die Next und Prevs genilt.
Hier die gesamte gepatchte Methode, wobei halt noch immer der Zweig für previousR unbehandelt ist:
Delphi-Quellcode:
      Function TXMLNodeList.Insert(Node, RNode: TXMLNode; previousR: Boolean = False): TXMLNode;
      var
        NPrev: TXMLNode;
      Begin
        If not (Node is TXMLNode) Then
          Raise EXMLException.Create(ClassType, 'Insert', @SInvalidNode);
        If (Assigned(_Parent) and (_Parent.InnerText <> '')) or (Assigned(_FirstNode)
            and ((_FirstNode.NodeType = xtCData) or (Node.NodeType = xtCData))) Then
          Raise EXMLException.Create(ClassType, 'Insert', @SIsTextNode, _Parent.Name);
        If Assigned(RNode) and (not (RNode is TXMLNode) or (RNode.ParentList <> Self)) Then
          Raise EXMLException.Create(ClassType, 'Insert', @SNodeNotInList);
        NPrev := Node.InnerPrev;
        If Assigned(Node.ParentList) Then Node := Node.ParentList.Remove(Node);
        Inc(_NodesCount);
        If previousR Then Begin
          (*If not Assigned(RNode) Then RNode := _FirstNode;

          If not Assigned(_FirstNode) or (_FirstNode = RNode) Then _FirstNode := Node;
          If not Assigned(_LastNode) Then _LastNode := Node;
          If Assigned(RNode) Then Begin
            If Assigned(RNode.InnerPrev) Then RNode.InnerPrev.InnerNext := Node;
            Node.InnerPrev := RNode.InnerPrev;
            Node.InnerNext := RNode;
            RNode.InnerPrev := Node;
          End;*)

        End Else Begin
          If not Assigned(RNode) Then RNode := _LastNode;

          If not Assigned(_FirstNode) Then _FirstNode := Node;
          If not Assigned(_LastNode) or (_FirstNode = RNode) Then _LastNode := Node;
          If Assigned(RNode) Then Begin
            If Assigned(RNode.InnerNext) Then RNode.InnerNext.InnerPrev := Node;
            If Assigned(Node.InnerPrev) Then Node.InnerPrev.InnerNext := RNode;
            Node.InnerNext := RNode.InnerNext;
            RNode.InnerPrev := NPrev;
            Node.InnerPrev := RNode;
            RNode.InnerNext := Node;
            Node.SetParent(self);
            Node.SetOwner(self.Owner);
          End;
        End;
        Node.CheckCrypted(True);
        Result := Node;
        DoNodeChange(Result, xcAddetNode);
      End;
Edit #wasweissich
Wenn beim Insert der LastNode betroffen ist, muss der noch in der Liste mit geupdated werden. Sonst geht in darauf folgenden Add() mächtig was schief!

Edit ...
Das letzte aber voraussichtlich . Wenn die beteiligten beiden Knoten keine Nachbarn sind, wird alles was zwischen den beiden war noch einseitig weggeschnitten. Node.Next.Prev und RNode.Prev.Next müssten noch behandelt werden.
Wenn man InnerNext und InnerPrev Setter spendieren würde, die gleich die Gegenrichtung mit anpassen, dürfte man sich viel Gehampel ersparen glaube ich.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)

Geändert von Medium (11. Okt 2010 um 09:37 Uhr)
  Mit Zitat antworten Zitat