Delphi-PRAXiS
Seite 4 von 35   « Erste     234 5614     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   himXML (gesprochen himix ML) (https://www.delphipraxis.net/130751-himxml-gesprochen-himix-ml.html)

xZise 21. Mai 2009 13:58

Re: himXML (gesprochen himixML)
 
Interessantes Projekt, besonders weil ich das XML Format eigentlich mag. Aber es lässt sich so schlecht verwenden. Ich werde dein Projekt mal testen ;) Vll. taugt es was :)

MfG
xZise

himitsu 22. Mai 2009 00:25

Re: himXML (gesprochen himixML)
 
Zitat:

Zitat von xZise
Aber es lässt sich so schlecht verwenden.

Einiges kommt mir zumindestens leichter vor ... hab auch "absichtlich" einiges anders definiert, als es z.B. beim (MS)XML-DOM der Fall ist.

Und wenn es dir dennoch zu schwer ist ... siehe Tools, da kannst du es (fast) wie TIniFile oder TRegistry verwenden, falls des dir leichter fällt. :angel2:

Zitat:

Zitat von xZise
Ich werde dein Projekt mal testen ;) Vll. taugt es was :)

viel Spaß und ich hoff's :?


neues Update oben
  • Indexfehler (Exception) in [Node].NodeList behoben
  • Fehler in den Deserialisierungen behoben und Einiges überarbeitet
    (die Deserialisierung für Variants und Records scheint nun zu laufen ... für Objekte kommt hoffentlich auch bald)
  • 2 Demos sind dazugekommen
    - Demo_Serialize.dpr - kleine Demonstration der (De)Serialisierungsfunktionen
    (besser im Debugger durchgehn, da man sonst noch nicht viel sieht)
    - Demo_Tree.dpr - eine XML-Datei einlesen und in einer TreeView anzeigen

[add]
soeben ist noch 'ne weitere Demo (SAXParser.dpr) entstanden ... es ist sowas wie ein SAX-Parser,
also die Daten werden schon wärend des Einlesens/Parsens ausgewertet und gleich wieder freigegeben
(dieses hab ich einfach in der schon vorhandenen Callback-Funktion gelöst)

man kann also auch mal Gigabyte-große Dateien parsen, ohne daß der geladene XML-Baum den RAM vollmacht
[/add]

SpeedTest.dpr liefert bei mir jetzt dieses Ergebnis
Code:
SetProcessAffinityMask: OK

use QueryPerformanceCounter

precreating used strings - do not create and convert this within the measuring
create:43


fill TXMLFile with 10.000 nodes and save this into a file
create:0  fill:15  save:9  free:4

fill TXMLDocument with 10.000 nodes and save this into a file
create:12  fill:6458  save:108  free:0


fill TXMLFile with 10.000 nodes, delete 8.000 nodes and save this into a file
create:0  fill:15  delete:409  save:4  free:0

fill TXMLDocument with 10.000 nodes, delete 8.000 nodes and save this into a file
create:0  fill:6303  delete:106310  save:97  free:0


fill TXMLFile with 10.000 nodes with attributes and save this into a file
create:0  fill:691  save:386  free:5

fill TXMLDocument with 10.000 nodes with attributes and save this into a file
create:0  fill:6589  save:122  free:0


fill TXMLFile with 100.000 nodes, save into and load this from a file
create:0  fill:166  save:70  free:37
create:0  load:245  free:33

fill TXMLDocument with 100.000 nodes, save into and load this from a file
create:0  fill:708145  save:348  free:0
create:0  load:331  free:94


fill TXMLFile with 10.000 nodes with attributes and search nodes
create:0  fill:697  search:2746  free:4

fill TXMLDocument with 10.000 nodes with attributes and search nodes
create:0  fill:6503  search:164476  free:0

press [enter]
ich glaub damit kann ich erstmal leben :angel:

xZise 22. Mai 2009 09:35

Re: himXML (gesprochen himixML)
 
Zitat:

Zitat von himitsu
Zitat:

Zitat von xZise
Aber es lässt sich so schlecht verwenden.

Einiges kommt mir zumindestens leichter vor ... hab auch "absichtlich" einiges anders definiert, als es z.B. beim (MS)XML-DOM der Fall ist.

Ich glaube du hast mich nicht richtig verstanden ;) Und zwar waren die bisherigen Lösungen (besonders das von MSXML) inner Unverhältnismäßig komplizierter. Wenn man also nicht zwingend XML benötigt, ist das via StringList immer einfacher gewesen... Deshalb setze ich so viel Hoffnung in das Projekt!

MfG
xZise

himitsu 22. Mai 2009 10:57

Re: himXML (gesprochen himixML)
 
Zitat:

Wenn man also nicht zwingend XML benötigt, ist das via StringList immer einfacher gewesen
also dagegen ist es schon noch etwas komplizierter, aber grad deswegen wird standardmäßig beim Erstellen die Grundstrucktur der XML schonmal erstellt
und man gleich loslegen :angel:

dieses für je das gleiche Ergebnis
Delphi-Quellcode:
XML := TXMLDocument.Create(nil);
XML.Active    := True;
XML.Version   := '1.0';
XML.StandAlone := 'yes';
XML.Encoding  := 'UTF-8';
XML.Options   := [doNodeAutoIndent];
XML.AddChild('xml');
Node := XML.DocumentElement.AddChild('Node1');
Node.Text     := 'Text';
XML.SaveToFile('test.xml');
XML.Free;
// gut, das .Free kann man sich sparren, wenn man auf IXMLDocument umsteigt

XML := TXMLFile.Create(nil);
Node := XML.RootNode.Nodes.Add('Node1');
Node.Data := 'Text';
XML.SaveToFile('test.xml');
XML.Free;

// oder gleich so ...

XML := TXMLFile.Create(nil);
XML.RootNode.Nodes['Node1'].Data := 'Text';
XML.SaveToFile('test.xml');
XML.Free;
bzw:
Delphi-Quellcode:
XML := TXMLFile.Create(nil);
XML.RootNode.Nodes['Node1\Node2'].Data := 'Text 1';
XML.RootNode.Nodes['Node1\Node3'].Data := 'Text 2';
XML.RootNode.Nodes['Node4'].Data      := 'Text 3';
XML.SaveToFile('test.xml');
XML.Free;
für
XML-Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<xml>
  <Node1>
    <Node2>Text 1</Node2>
    <Node3>Text 2</Node3>
  </Node1>
  <Node4>Text 3</Node4>
</xml>
per Standard werden (bis auf Kommentare) alle Steuer-Tags (ala <?...?> , <!...> und <![CDATA[...]]> ) rausgefiltert und (bis auf die ungefilterten NF-Funktionen) im Baum nicht aufgelistet. (siehe XML.Options)


ja und wenn es wirklich einfach sein soll ... nja, ist quasi eine INI im XML-Format :nerd:
Delphi-Quellcode:
Var Ini: TXMLIniFile;

Ini := TXMLIniFile.Create('myOptions.xml');
Try
  Ini.WriteString('Section', 'Ident 1', S);
Finally
  Ini.Free;
End;
XML-Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<ini>
  <section name="Section">
    <ident name="Ident 1">irgendein String</ident>
  </section>
</ini>

hab auch grad 'nen Fehler beim AutoUpdate der XML-Ini entdeckt (kleine Exception beim .Free)
und gleich noch eine Parameterprüfung dort mit eingebaut
wird beim nächsten Update mit hochgeladen

himitsu 22. Mai 2009 14:22

Re: himXML (gesprochen himixML)
 
die dort drüben aufgetauchte Exception wurde behoben
> Schnelle XML Lib für große Dateien gesucht #35
(kleiner Fehler beim Nachladen wärend ein Attribut ausgelesen wurde)

Code:
fill TXMLFile with 4.000.000 nodes, save into and load this from a file
create:0  fill:413022  save:404106  free:3261
create:0  load:643563  free:3104

fill TXMLDocument with 4.000.000 nodes, save into and load this from a file
...
also 10,7 Minuten für 12.000.006 Tags und Attribute einer 386 MB-Datei

Im "pseudo" SAX-Mode wird in der Demo (SpeedTest.dpr) eine belibig große Datei mit nur 3 MB RAM innerhalb von 12 Minuten (0,5 MB/s) ausgelesen (also abzüglich der precreated-Arrays für die anderen Tests).
OK, ist nicht wirklich schnell, aber es ist ja auch 'ne DOM-Lib

Aktuell bin ich erstmal froh, daß es soweit läuft und Optimierungspotential gibt es noch (pro Byte zwei Funktionsaufrufe ... aber erstmal andere Fehler entdecken und dann kommt das dran)


[add]
die Demo_Tree.exe bitte neu komilieren, sonst kommt es noch zur obengenannten exception, bei Dateien über 64 KB
alles neu kompiliert

xZise 23. Mai 2009 09:00

Re: himXML (gesprochen himixML)
 
Zitat:

Zitat von himitsu
Zitat:

Wenn man also nicht zwingend XML benötigt, ist das via StringList immer einfacher gewesen
also dagegen ist es schon noch etwas komplizierter, aber grad deswegen wird standardmäßig beim Erstellen die Grundstrucktur der XML schonmal erstellt[...]

Naja als Alternative für XML z.B. habe ich das folgendermaßen:
Code:
computers.count=1
computers[0].name=Hallo
computers[0].LastIPByte=101
computers[0].Left=100
computers[0].Top=25
In XML sähe das dann so aus:
Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<xml>
  <Computers>
    <Computer>
      <Name>Hallo</Name>
      <LastIPByte>101</LastIPByte>
      <Position>
        <Left>100</Left>
        <Top>25</Top>
      </Position>
    </Computer>
  </Computers>
</xml>
Da ließe sich bestimmt noch einiges verbessern (mit Attributen z.B.) ... Aber genau aus diesem Grund möchte ich ja mal deine Unit testen, wobei ich im Moment noch nicht weiß wo (außer im obigen Beispiel... Aber da sind die Daten auf einen Computer in der Schule) :)

MfG
xZise

himitsu 23. Mai 2009 17:11

Re: himXML (gesprochen himixML)
 
entweder du probierst es mal mit der Serialisierung (Beispiele siehe Projekt Demo_Serialize).
> dieses speichert aber bei Objekten nur published Properties (für "alles" Andere bietet mir Delphi keine oder nur unzureichende Informationen)

z.B. so in dieser Art:
Delphi-Quellcode:
XML := TXMLFile.Create;
Try
  XML.RootNode.AddNode('Computers').Serialize(Computers, ....);
  XML.SaveToFile('Computers.xml');
Finally
  XML.Free;
End;

XML := TXMLFile.Create;
Try
  XML.LoadFromFile('Computers.xml');
  XML.RootNode.AddNode('Computers').Deserialize(Computers, ....);
Finally
  XML.Free;
End;
oder du machst es selber, was aber auch nicht sooooo schwer ist

dieses ergibt dein XML-Beispiel (nur noch mit dem Count-Node):

XML-Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<xml>
  <Computers>
    <Count>1</Count>
    <Computer>
      <Name>Hallo</Name>
      <LastIPByte>101</LastIPByte>
      <Position>
        <Left>100</Left>
        <Top>25</Top>
      </Position>
    </Computer>
  </Computers>
</xml>
Delphi-Quellcode:
// Speichern
XML := TXMLFile.Create;
Try
  XML.RootNode.AddNode('Computers\Count').Data := Computers.Count;
  For i := 0 to Computers.Count - 1 do
    With XML.RootNode.AddNode('Computers\Computer') do Begin
      AddNode('Name').Data         := Computers[i].Name;
      AddNode('LastIPByte').Data   := Computers[i].LastIPByte;
      AddNode('Position\Left').Data := Computers[i].Left;
      AddNode('Position\Top').Data := Computers[i].Top;
    End;
  XML.SaveToFile('Computers.xml');
Finally
  XML.Free;
End;

// laden
XML := TXMLFile.Create;
Try
  XML.LoadFromFile('Computers.xml');
  Computers.Count := XML.RootNode.Node['Computers\Count'].Data;
  For i := 0 to Computers.Count - 1 do
    With XML.RootNode.NodeList['Computers\Computer'][i] do Begin
      Computers[i].Name      := Node['Name'].Data;
      Computers[i].LastIPByte := Node['LastIPByte'].Data;
      Computers[i].Left      := Node['Position\Left'].Data;
      Computers[i].Top       := Node['Position\Top'].Data;
    End;
Finally
  XML.Free;
End;
und mit Attributen:
XML-Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<xml>
  <Computers Count="1">
    <Computer Name="Hallo" LastIPByte="101" Left="100" Top="25">
  </Computers>
</xml>
Delphi-Quellcode:
// Speichern
XML := TXMLFile.Create;
Try
  XML.RootNode.AddNode('Computers').Attributes['Count'] := Computers.Count;
  For i := 0 to Computers.Count - 1 do
    With XML.RootNode.AddNode('Computers\Computer') do Begin
      Attribute['Name']      := Computers[i].Name;
      Attribute['LastIPByte'] := Computers[i].LastIPByte;
      Attribute['Left']      := Computers[i].Left;
      Attribute['Top']       := Computers[i].Top;
    End;
  XML.SaveToFile('Computers.xml');
Finally
  XML.Free;
End;

// laden
XML := TXMLFile.Create;
Try
  XML.LoadFromFile('Computers.xml');
  Computers.Count := XML.RootNode.Node['Computers'].Attribute['Count'];
  For i := 0 to Computers.Count - 1 do
    With XML.RootNode.NodeList['Computers\Computer'][i] do Begin
      Computers[i].Name      := Attribute['Name'];
      Computers[i].LastIPByte := Attribute['LastIPByte'];
      Computers[i].Left      := Attribute['Left'];
      Computers[i].Top       := Attribute['Top'];
    End;
Finally
  XML.Free;
End;
man könnte auch Count weglassen und zählen:
Delphi-Quellcode:
// Speichern
XML := TXMLFile.Create;
Try
  For i := 0 to Computers.Count - 1 do
    With XML.RootNode.AddNode('Computers\Computer') do Begin
      ...
    End;
  XML.SaveToFile('Computers.xml');
Finally
  XML.Free;
End;

// laden
XML := TXMLFile.Create;
Try
  XML.LoadFromFile('Computers.xml');
  Computers.Count := Length(XML.RootNode.Node['Computers'].NodeList['Computer']);
  For i := 0 to Computers.Count - 1 do
    With XML.RootNode.NodeList['Computers\Computer'][i] do Begin
      ...
    End;
Finally
  XML.Free;
End;

// laden 2 (wenn es eh keine anderen Subnodes im Node "Computers" gibt)
XML := TXMLFile.Create;
Try
  XML.LoadFromFile('Computers.xml');
  Computers.Count := XML.RootNode.Node['Computers'].Nodes.Count;
  For i := 0 to Computers.Count - 1 do
    With XML.RootNode.Node['Computers'].Node[i] do Begin
      ...
    End;
Finally
  XML.Free;
End;
ich hoff mal, es ist jetzt nicht zu schwer?

Satty67 23. Mai 2009 17:26

Re: himXML (gesprochen himixML)
 
XML-Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<xml>
  <Computers>
    <Count>1</Count>
    <Computer>
      <Name>Hallo</Name>
      <LastIPByte>101</LastIPByte>
      <Position>
        <Left>100</Left>
        <Top>25</Top>
      </Position>
    </Computer>
  </Computers>
</xml>
Was mir da gerade auffällt ist der enorme Overhead. Bei XML gibt es ja auch Komprimierung, ist da was für himXML geplant (evtl. halt erst in späteren Versionen).

himitsu 23. Mai 2009 19:39

Re: himXML (gesprochen himixML)
 
Wenn du die Zeilenumbrüche und Einrückung meinst ... nimm einfach xoNodeAutoIndent aus den Optionen (.Options) raus :angel:

PS: die CDATA-Sektion wird seit vorgestern standardmäßig nicht mehr umgebrochen (diese hat, zusammen mit den Unknown-Nodes, eine eigene Behandlung bekommen)

hierfür gibt es also xoNodeAutoIndent, xoCDataNotAutoIndent und xoFullEmptyElements

insgesamt gibt es derzeit (die Fettgedruckten sind standardmäßig aktiv)
  • xoChangeInvalidChars - beim Einlesen und beim Zuweisen von Text an Nodes und Attribute werden ungültige Zeichen ersetzt
  • xoCaseSensitive - die Node/Attributsuche ist casesensitiv (normaler Weise sind XML-Dateien laut XML-Spezifikation casesensitiv)
  • xoHideInstructionNode - Instruktionen <?name ...?> werden rausgefiltert
    (keine Filterung in den ungefilterten NF-Funktionen > .Node = gefiltert > .NodeNF = ungefiltert)
  • xoHideTypedefNodes - Instruktion <!name ...?> werden rausgefiltert
  • xoHideCDataNodes - CDATA <[CDATA[...]]> wird rausgefiltert
  • xoHideCommentNodes - Kommentare <--...--> werden rausgefiltert
  • xoHideUnknownNodes - xtUnknown wird rausgefiltert
    (das sind Nodes mit "Text" an "falschen" Stellen ... z.B. <a><b/>unknown</a> ... Node "a" enthält einen Subnode "b" und "Text" ... falls jemandem ein besserer Name für diese Art von Nodes einfällt > bitte hier rufen)
  • xoNodeAutoCreate - beim Zugriff auf nicht existierende Nodes werden diese versucht zu erstellen
  • xoNodeAutoIndent - fügt Zeilenumbrüche und die Tag-Einrückung ein
  • xoCDataNotAutoIndent zusammen mit xoNodeAutoIndent - keine Einrükung für CDATA-Tags
  • xoFullEmptyElements - keine kurzen Tags - kein <tag /> sondern <tag></tag>
  • xoAutoSaveOnClose - beim .Free wird die geöffnete XML-Datei automatisch gespeichert

man kann den Standard aber allerdings über TXMLFile.DefaultOptions global für alle nachfolgend erstellten TXMLFile-Instanzen ändern

Satty67 23. Mai 2009 21:58

Re: himXML (gesprochen himixML)
 
Hmm, bekomme es jetzt mit TDE2006 nicht mehr compiliert und leider immer brav die alte Version gelöscht. :gruebel:

Geht schon bei __CompareBlock los (Char <> WideChar). Du hast ja selber TDE2006, falls nicht poste ich eine genauere Fehlermeldung.


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:48 Uhr.
Seite 4 von 35   « Erste     234 5614     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz