AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte himXML (gesprochen himix ML)
Thema durchsuchen
Ansicht
Themen-Optionen

himXML (gesprochen himix ML)

Ein Thema von himitsu · begonnen am 12. Mär 2009 · letzter Beitrag vom 11. Nov 2020
Antwort Antwort
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#1

AW: himXML (gesprochen himix ML)

  Alt 9. Okt 2010, 18:17
Da es ja ein Insert(), kein Replace() ist, sollte der ja eigentlich einfach nur verrutschen
"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)
  Mit Zitat antworten Zitat
Benutzerbild von xZise
xZise

Registriert seit: 3. Mär 2006
Ort: Waldbronn
4.303 Beiträge
 
Delphi 2009 Professional
 
#2

AW: himXML (gesprochen himix ML)

  Alt 10. Okt 2010, 12:35
Moin,
wenn du allerdings in der Liste mehrere Nodes zwischen n und f hast.
Zum Beispiel:
Code:
abc n opq f ghi
Dann sieht das danach so aus:
Code:
abc n opq n f ghi
Code:
abc opq n f ghi
Aber ein austauschen sieht für mich so aus:
Code:
abc f opq n ghi
MfG
Fabian
Fabian
Eigentlich hat MS Windows ab Vista den Hang zur Selbstzerstörung abgewöhnt – mkinzler
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#3

AW: himXML (gesprochen himix ML)

  Alt 10. Okt 2010, 13:19
Das ist nicht gegeben. n unf f stehen sowohl in der Listbox, als auch im XMLNode direkt hintereinander. Dessen bin ich mir sicher, da ich die Listbox bei jeder Änderung im XML immer frisch aus dem Node befülle, und dabei nicht auf XMLNode.NextNode zurückgreife, sondern wirklich per Index durch XMLNode.Nodes[i] iteriere. f ist immer der Folgeknoten von n (deswegen f ).
Auf diese Weise habe ich mit TList auch schon öfter gearbeitet, was okay war. Die Funktion die ich damit realisieren will ist einfach, dass man mit 2 Buttons "hoch" und "runter" ein Item pro Klick um einen Platz rauf oder runter wandern lassen kann. Dies innerhalb der Listbox allein reicht jedoch nicht, sondern muss schon in der Datenhaltung darunter ebenfalls passieren, dem XML.

Edit: Um das eigentliche Problem nochmal zu verdeutlichen: Ein via Insert() eingefügter Node wird nachher nicht mehr im Array des Elternknotens gefunden. Sowohl ParentNode.IndexOf(n) als auch n.Index liefern -1, obgleich ich den Knoten per n := ParentNode.Nodes['#NodeName>Attribut1=aValue'] ermittelt habe.

Meine Verschiebung geht daher, aber auch nur, wenn kein beteiligter Knoten zuvor schon ein mal verschoben wurde.

Besonders ärgerlich dabei: Ein Haltepunkt in der Insert() Funktion in der himXML.pas wird zur Laufzeit deaktiviert. Ich kann also garnicht nachvollziehen, was da genau passiert - oder auch nicht Sogar mit F7 reinsteppen tut nicht, der Debugger hüpft einfach drüber.
"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 (10. Okt 2010 um 15:30 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.388 Beiträge
 
Delphi 12 Athens
 
#4

AW: himXML (gesprochen himix ML)

  Alt 10. Okt 2010, 20:48
@geskill: kommst auch gleich dran

@Medium:
die 1 vor die 3 verschieben
Delphi-Quellcode:
n := XML.RootNode.Nodes['#Element>ID=1'];
f := XML.RootNode.Nodes['#Element>ID=3'];
XML.RootNode.Nodes.Insert(n, f, True);
oder die 1 ausschneiden und vor der 3 wieder einfügen
Delphi-Quellcode:
n := XML.RootNode.Nodes.Remove('#Element>ID=1');
f := XML.RootNode.Nodes['#Element>ID=3'];
XML.RootNode.Nodes.Insert(n, f, True);
Ich würde aber Ersteres bevorzugen, denn falls was beim Einfügen schief geht (Exception), dann würde f wild in der Gegend rumliegen (Speicherleck).

bzw, die 1 hinter die 3 verschieben
Delphi-Quellcode:
n := XML.RootNode.Nodes['#Element>ID=1'];
f := XML.RootNode.Nodes['#Element>ID=3'];
XML.RootNode.Nodes.Insert(n, f);
oder die 1 ausschneiden und nach der 3 wieder einfügen
Delphi-Quellcode:
n := XML.RootNode.Nodes.Remove('#Element>ID=1');
f := XML.RootNode.Nodes['#Element>ID=3'];
XML.RootNode.Nodes.Insert(n, f);

Nun aber noch 2 kleine Fehlerkorrekturen:
- In TXMLNodeList.Remove das "not" entfernen
- und nach dem Insert waren wirklich ein paar Zeiger fehlerhaft
Delphi-Quellcode:
    Function TXMLNodeList.Insert(Node, RNode: TXMLNode; previousR: Boolean = False): 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;
            Node.InnerPrev := RNode;
            RNode.InnerNext := Node;
          End;
        End;
        Node.CheckCrypted(True);
        Result := Node;
        DoNodeChange(Result, xcAddetNode);
      End;
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (10. Okt 2010 um 20:51 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.388 Beiträge
 
Delphi 12 Athens
 
#5

AW: himXML (gesprochen himix ML)

  Alt 10. Okt 2010, 21:04
@geskill:
Konnte deinen Fehler leider nicht reproduzieren.

Solange man nicht "manuell" im Quellcode die .Version setzt oder das Versions-Attribut verändert, sollte eigentlich beim Speichern niemal diese Fehlermeldung erscheinen können.
(beim Auslesen sollten nur bekannte XML-Version erkannt/zugelassen werden, weswegen beim Speichern eigentlich keine unbekannte Version vorliegen dürfte)

Könntest du mir eine Demoanwendung zukommen lassen, welche dieser Verhalten zeigt?



PS: .DefaultTextIndent legt die "Standard"-Einstellung für zukünftige Instanzen von TXMLFile fest.
.TextIndent repräsentiert die Einstellung der aktuellen Instanz.

Du wolltest also bestimmt TextIndent := #9; verwenden.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (10. Okt 2010 um 21:11 Uhr)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#6

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
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.388 Beiträge
 
Delphi 12 Athens
 
#7

AW: himXML (gesprochen himix ML)

  Alt 12. Okt 2010, 01:30
Einer der Gründe, warum ich das Speichermanagement etwas fast komplett überarbeite.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

(?)

LinkBack to this Thread

Erstellt von For Type Datum
xml - MSXML alternative - Stack Overflow This thread Refback 28. Jun 2011 15:34

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:48 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