Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   XML (https://www.delphipraxis.net/46-xml/)
-   -   Delphi Datei bearbeiten und nur Teile wieder speichern (https://www.delphipraxis.net/109379-datei-bearbeiten-und-nur-teile-wieder-speichern.html)

Hoschie 29. Feb 2008 07:49


Datei bearbeiten und nur Teile wieder speichern
 
Guten Morgen Delphi-Meister,

entschuldigt den merkwürdigen Titel, aber genau das beschreibt meine Frage am besten.
Zur Situation:
Ich habe eine XML Datei, die aus mehreren Elementen besteht. Zum Beispiel :
Delphi-Quellcode:
<root>
  <Element1>
    <Element1.1>
      <Element1.1.1>bla</Element1.1>
      <Element1.1.2>bla</Element1.2>
    </Element1.1>
  </Element1>
  ......usw.....
Nun möchte ich alles ab z.B. Element3 bis zum Schluss auslesen und in eine andere Datei schreiben. Die root soll erhalten beliben. Habe schon die SuFu genutzt aber nichts erklärendes gefunden.
Ist hier vielleicht jemand der mir das erklären kann? Es muss ja nicht unbedingt eine Lösung sein, eine Erklärung mit dem ein oder anderen Hinweis wäre schön. Erarbeiten würde ich das dann gerne selber.

Gruß
Hoschie

alleinherrscher 29. Feb 2008 08:34

Re: Datei bearbeiten und nur Teile wieder speichern
 
Wie ließt du denn die Datei ein? Also wenn du sie zeilenweise mit Readln einließt sollte das eig. kein Problem sein:

Du ließt alles bis zu der Zeile nach <root> ein:

(is jetzt n bisschen primitiver code)

Delphi-Quellcode:

assignfile(textfile1,filename1); //textfile1 aus dem gelesen werden soll
reset(textfile1);

assignfile(textfile2,filename2); //textfile2 in das geschrieben werden soll
rewrite(textfile2);

a:='';
while (not a='<root>') or (not eof(textfile1)) do
begin
  readln(textfile1,a);
  writeln(textfile2,a);
end;

a:='';
while (not a='Element3') or (not eof(textfile1)) do
  readln(textfile1,a);

a:='';
while (not eof(textfile1)) do
begin
  readln(textfile1,a);
  writeln(textfile2,a);
end;

closefile(textfile1);
closefile(textfile2);
Das ganze könnte man dann in eine procedure schreiben, z.B.

Delphi-Quellcode:

procedure CopyLines(FromFile,ToFile:textfile;
                    TerminateString:String;
                    seekonly:boolean);
var a:string;
begin

a:='';
while (TerminateString='' or (not a=TerminateString)) or (not eof(textfile1)) do
begin
  readln(textfile1,a);
  if not seekonly then writeln(textfile2,a);
end;


end;
Mit der Procedur würde dein Programm dann so aussehen:

Delphi-Quellcode:
assignfile(textfile1,filename1); //textfile1 aus dem gelesen werden soll
reset(textfile1);
assignfile(textfile2,filename2); //textfile2 in das geschrieben werden soll
rewrite(textfile2);

CopyLines(textfile1,textfile2,'<root>',false);
CopyLines(textfile1,textfile2,'Eingabe3',true);
CopyLines(textfile1,textfile2,'',false);

Hoschie 29. Feb 2008 09:05

Re: Datei bearbeiten und nur Teile wieder speichern
 
Moin,

ist es denn so, dass er automatisch alle Unterelemete von Element3 dann mit einliest und wegspeichert?
Und wie übernimmt er dann die schließenden Tags ?

Aber danke schonmal.

alleinherrscher 29. Feb 2008 09:31

Re: Datei bearbeiten und nur Teile wieder speichern
 
Oh, ahso, du willst die unterelemente mit ham...dann sag doch, dass er bis zu element4 speichern soll und programmier die procedur so um, dass er TerminateString selbst nicht mehr mitspeichert, wäre das ne Idee?

Hoschie 29. Feb 2008 20:47

Re: Datei bearbeiten und nur Teile wieder speichern
 
Nabend,


da muss ich mich jetzt erstmal reinwurschtln. Ich versuchs mal, schauen wir was dabei rauskommt.
Vielen Dank erstmal, wenns Probleme gibt, melde ich mich wieder :mrgreen:

Gruß
Hoschie

marabu 1. Mär 2008 12:55

Re: Datei bearbeiten und nur Teile wieder speichern
 
Hallo Hoschie,

XML-Dokumente lassen sich am besten verarbeiten, wenn du sie in ein Document Object Model (DOM) überführst. Die Software-Industrie hat gemeinsam ein solches Modell spezifiziert und es gibt eine ganze Reihe von Implementierungen. Eine steckt z.B. in den Microsoft XML Core Services (MSXML4.DLL oder neuer), die auf jedem Windows PC vorhanden sind. Falls deine Delphi-Version ohne die Unit MSXML daher kommt, dann kannst du für diese DLL einen Wrapper (MSXML2) erzeugen.

Ich muss dein Problem etwas umformulieren, damit ich ein Beispiel geben kann: In einem XML-Dokument sollen die ersten beiden Unterknoten des Wurzelknoten entfernt werden?

Delphi-Quellcode:
uses
  MSXML;

var
  fnOld, fnNew: TFileName;
  xd: IXMLDOMDocument;
begin
  // fnOld := 'c:\daten\dp\books.xml';
  // fnNew := 'c:\daten\dp\books-mod.xml';
  xd := CoDomDocument.Create;
  xd.async := False;
  if xd.load(fnOld) then
  begin
    with xd.documentElement do
    begin
      removeChild(childNodes[1]);
      removeChild(childNodes[0]);
    end;
    xd.save(fnNew);
  end;
end;
Freundliche Grüße

Hoschie 1. Mär 2008 13:51

Re: Datei bearbeiten und nur Teile wieder speichern
 
Hi,

das ist ein interessanter Ansatz, so könnte ich eventuell sogar schon vor dem abspeichern, das rausfiltern was ich benötige und halte so die Datenmenge in der Datei um ein vielfaches kleiner.

Im Endeffekt benötige ich nur ein kleinen Teil der runtergeladenen Datei. Diese sieht ungefähr so aus :
Delphi-Quellcode:
<root>
  <sprache>
    <text></text>
  </sprache>
  <systemdaten>
    <einstellungen></einstellungen>
    <zeiten></zeiten>
  </systemdaten>
  <daten>
    <id></id>
    <name></name>
    <Lehrgänge></lehrgänge>
  </daten>
  <Orte>
    <stadt1></stadt1>
    <stadt2></stadt2>
  </Orte>
</root>
Der kleine Teil, den ich jetzt benötige liegt in <daten> und dann <Lehrgänge>, den anderen Kram brauche ich nicht. Verhält es sich da änlich mit den ChildNodes ? Was wäre einfacher, die anderen zu entfernen oder den benötigten rauszukopieren ?

Vielen Dank,

Hoschie

Bernhard Geyer 1. Mär 2008 14:00

Re: Datei bearbeiten und nur Teile wieder speichern
 
Zitat:

Zitat von marabu
XML-Dokumente lassen sich am besten verarbeiten, wenn du sie in ein Document Object Model (DOM) überführst.

Full Ack! Jede Lösung mittels "normale" Stringfunktionen wird spätestens dann scheitern wenn Elemente mit Sonderzeichen eleminiert werden müssen und die Codierung immer unterschiedlich ist. Auch sind Zeilenumbrüche (CRLF) nicht zwingen in XML-Dateien nötig. Also lesen jeweiliger Elemente mit readln wird dann auch probleme bereiten.

Hoschie 1. Mär 2008 17:25

Re: Datei bearbeiten und nur Teile wieder speichern
 
Habt Ihr vielleicht ein paar Tipps, wie ds mit dem Wrapper funktioniert ? Ich denke nicht, dass die 2005 PE mit MSXML Unit ohne weiteres läuft, jedenfalls kennt er die nicht. Die Suche konnte mir da nicht weiterhelfen, oder habe ich etwas übersehen ?

Und habt ihr vielleicht dazu noch was :
Zitat:

Der kleine Teil, den ich jetzt benötige liegt in <daten> und dann <Lehrgänge>, den anderen Kram brauche ich nicht. Verhält es sich da änlich mit den ChildNodes ? Was wäre einfacher, die anderen zu entfernen oder den benötigten rauszukopieren ?
Gruß
Hoschie

marabu 1. Mär 2008 17:43

Re: Datei bearbeiten und nur Teile wieder speichern
 
In der DP Code-Library habe ich etwas gefunden: MSXML

Da ist bestimmt auch für dich etwas dabei.

Zu deinem Projekt: Gibt es da nur ein einziges Element Lehrgänge?

XML ist übrigens case-sensitive! Lehrgänge <> lehrgänge

Hoschie 1. Mär 2008 17:48

Re: Datei bearbeiten und nur Teile wieder speichern
 
Jo, gibt nur eins und in dem Element Lehrgänge sind dann viele Unterelemente, und genau die benötige ich :-D

Das beste wäre, wenn am Ende sämtliche Unterlemente der Lehrgänge in einer neuen Datei zusammengelegt werden.

Gruß
Hoschie

Edit:
Zitat:

XML ist übrigens case-sensitive! Lehrgänge <> lehrgänge
Danke!! :mrgreen: Das wäre das erste typische HÄ??? wenns läuft, aber nix passiert.

marabu 1. Mär 2008 18:14

Re: Datei bearbeiten und nur Teile wieder speichern
 
Aus der Fülle der möglichen Vorgehensweisen stelle ich dir mal zwei vor:

(1) Transformation per XSLT

XML-Code:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

  <xsl:output method="xml" version="1.0" encoding="iso-8859-1" indent="yes"/>

  <xsl:template match="/">
    <xsl:apply-templates select="/root/daten/lehrgänge"/>
  </xsl:template>
 
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="comment()"/>

</xsl:stylesheet>
Mit diesem Script wird zur Not auch auf der Kommandozeile (MSXSL.EXE bekommst du bei Microsoft, wenn du es noch nicht hast) dein Dokument umgeformt:

Code:
msxsl hoschie.xml extract.xsl -o extract.xml
Oder mit Delphi:

Delphi-Quellcode:
// uses ActiveX, Msxml, Classes, SysUtils

var
  fnOld, fnNew, fnStyle: TFileName;
  xdData, xdStyle: IXMLDOMDocument;
  fs: TFileStream;
begin
  fnOld := 'c:\daten\dp\hoschie.xml';
  fnStyle := 'c:\daten\dp\extract.xsl';
  fnNew := 'c:\daten\dp\extract.xml';
  xdData := CoDomDocument.Create;
  xdData.async := False;
  xdStyle := CoDomDocument.Create;
  xdStyle.async := False;
  if xdStyle.load(fnStyle) then
    if xdData.load(fnOld) then
    begin
      fs := TFileStream.Create(fnNew, fmCreate);
      try
        xdData.transformNodeToObject(xdStyle, TStreamAdapter.Create(fs, soReference) as IStream);
      finally
        fs.Free;
      end;
    end else ShowMessage('XML syntax error: ' + xdData.parseError.reason)
  else ShowMessage('XSLT syntax error: ' + xdStyle.parseError.reason)
end;
(2) Beinahe vergessen: Selektieren und Clonen

Delphi-Quellcode:
var
  fnOld, fnNew: TFileName;
  xdOld, xdNew: IXMLDOMDocument;
  xn: IXMLDOMNode;
begin
  fnOld := 'c:\daten\dp\hoschie.xml';
  fnNew := 'c:\daten\dp\extract.xml';
  xdOld := CoDomDocument.Create;
  xdOld.async := False;
  xdNew := CoDomDocument.Create;
  xdNew.async := False;
  if xdOld.load(fnOld) then
  begin
    xn := xdOld.selectSingleNode('/root/daten/lehrgänge');
    if Assigned(xn) then
    begin
      xdNew.documentElement := xn.cloneNode(True) as IXMLDOMElement;
      xdNew.save(fnNew);
    end else ShowMessage('keine lehrgänge gefunden')
  end else ShowMessage(xdOld.parseError.reason);
end;
Ich finde beide schön.

Hoschie 1. Mär 2008 18:59

Re: Datei bearbeiten und nur Teile wieder speichern
 
Und wieder ich :-D
Schön sind die Varianten alle :thumb:

Nochmal zum Verständnis, sorry wenn das etwas stümperhaft klingt:

Ich hole mir eine XML Datei aus dem Web, die lade ich so, wie du es mir in dem anderen Post mal vorgeschlagen hast :

Delphi-Quellcode:
doc := WebBrowser1.Document;
    ws := doc.XMLDocument.XML;
kann ich direkt aus der Variablen ws jetzt den XML-Code umwandeln, oder muss ich den erst in eine Datei speichern und dann die Datei umwandeln.
Theoretisch könnte ich mir eine komplette Schreib und Speicher Abfolge sparen, wenn ich aus der Variablen das umwandeln könnte und die unbenötigten Teile filtern könnte.
Oder sehe ich da was falsch ?

Danke

marabu 1. Mär 2008 19:52

Re: Datei bearbeiten und nur Teile wieder speichern
 
Huch, nein - du musst nicht über das Dateisystem gehen:

Delphi-Quellcode:
function GetXmlDocument(doc: OleVariant): IXMLDOMDocument;
var
  u: IUnknown;
  xd: IXMLDOMDocument;
begin
  u := doc.XMLDocument;
  if not Assigned(u) or not Succeeded(u.QueryInterface(IXMLDOMDocument, Result))
    then Result := nil;
end;

// How to use

var
  xd: IXMLDOMDocument;
begin
  xd := GetXmlDocument(WebBrowser.Document);
end;

Hoschie 1. Mär 2008 20:59

Re: Datei bearbeiten und nur Teile wieder speichern
 
Ich versuche das gerade mal auf mich umzusetzen allerdings funktioniert dies hier nicht:
Delphi-Quellcode:
  xdOld := CoDomDocument.Create;
  xdOld.async := False;
  xdNew := CoDomDocument.Create;
  xdNew.async := False;
Er hat auch gar nicht CoDomDocument in der Programmierhilfe.

Gruß
Hoschie

marabu 1. Mär 2008 21:04

Re: Datei bearbeiten und nur Teile wieder speichern
 
Welche MSXML-Unit hast du denn mit USES eingebunden?

Hoschie 1. Mär 2008 21:10

Re: Datei bearbeiten und nur Teile wieder speichern
 
Ich habe aus dem Link, den du gepostet hast nach der Anweisung dort die MSXML2_TLB eingebunden.

marabu 2. Mär 2008 10:00

Re: Datei bearbeiten und nur Teile wieder speichern
 
Moin,

anscheinend hast du dabei einen Fehler gemacht, sonst würde er die dort enthaltene Klasse CoDomDocument kennen.

Kann es sein, dass du die Unit MSXML2 zwar deinem Projekt hinzugefügt hast, aber nicht in die USES-Anweisung derjenigen Unit aufgenommen hast, in welcher der Compiler-Fehler auftritt?

Freundliche Grüße

Hoschie 2. Mär 2008 11:23

Re: Datei bearbeiten und nur Teile wieder speichern
 
Moin,

also im Uses habe ich die MSXML2_TLB drin, sonst würde er doch auch die IXMLDOMDocument nicht kennen, oder ? Bin etwas verwirrt jetzt, aber das ist nicht unnormal :-D

Gruß
Hoschie

marabu 2. Mär 2008 12:33

Re: Datei bearbeiten und nur Teile wieder speichern
 
Ich habe mir jetzt mal die von sakura bereit gestellten MSXML-Wrapper angeschaut. Die von ihm verwendete Version des Hilfsprogramms TLIBIMP korrigiert nicht nur Schlüsselwort-Kollisionen bei den Bezeichnern, sondern darüber hinaus auch einige Bezeichner, die vermutlich in neueren Versionen von Delphi zu Kollisionen mit CodeGear-eigenen Bezeichnern führen könnten. Das haben frühere Versionen des Hilfsprogramms nicht gemacht.

Du musst aufgrund der Umbennungen mit ComsDOMDocument arbeiten und nicht mit CoDomDocument. Fast der gesamte Beispielcode in der DP verwendet die alten Bezeichner, so dass du generell aufpassen und die Kommentare am Anfang der Units genau studieren musst.

Hoschie 2. Mär 2008 13:17

Re: Datei bearbeiten und nur Teile wieder speichern
 
Ich werde es gleich nachher mal ausprobieren.

Lob und Anerkennung für Deine Geduld und Deine Mühen(vor allem der Geduld :-D ).

Gruß
Hoschie

Hoschie 2. Mär 2008 14:45

Re: Datei bearbeiten und nur Teile wieder speichern
 
OK, es will nicht funktionieren.

Hier mal mein Quellcode :

Delphi-Quellcode:
// in der Uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, OleCtrls, SHDocVw_TLB, ActiveX, MSXML2_TLB;

// Prozedur mit Fehler
procedure TForm2.saveBody ();
var  // Variablendeklaration
fnNew: TFileName;
ws,s: WideString;
doc: OleVariant;
f, log: TextFile;
u, xdNew: IXMLDOMDocument;
xd: IXMLDOMNode;

// die Sachen hier vor habe ich aus Platzgründen rausgelassen, überwiegend Kommentar und auskommentiertes

    fnNew:=('c:\Scan.xml');
    u:=GetXMLDocument(WebBrowser1.Document);
    xd:=u.selectSingleNode('/root/data');
    xdNew.ComsDOMDocument.Create; // hier Fehlermeldung : [Fehler] Unit2.pas(125): E2003 Undefinierter Bezeichner: 'ComsDOMDocument'

    xdNew.documentElement:= xd.cloneNode(True) as IXMLDOMElement;
    xdNew.save(fnNew);
Ist wahrscheinlich etwas was euch ins Auge springt und bei mir abprallt.

marabu 2. Mär 2008 16:09

Re: Datei bearbeiten und nur Teile wieder speichern
 
Vergleiche mal:

Delphi-Quellcode:
xdNew := CoDomDocument.Create; // mein Code

xdNew.ComsDOMDocument.Create; // hier Fehlermeldung
Hast du dich da vertippt?

Hoschie 2. Mär 2008 16:52

Re: Datei bearbeiten und nur Teile wieder speichern
 
Äh Hi, :oops: :oops:

Zitat:

Ist wahrscheinlich etwas was euch ins Auge springt und bei mir abprallt.
:wall:
Entschuldige, von Blindheit geschlagen, aber ein Beweis fürs nicht einfach nur kopieren :roll: .

Darf ich noch Fragen, wie ich jetzt weitere Daten in der Datei anhänge, also in dieselbe Datei reinschreibe. So in der Art Append bei Stringbehandlung ?

Und dann sollte es das gewesen sein.

Vielen Dank. :thumb: :thumb:

marabu 2. Mär 2008 17:07

Re: Datei bearbeiten und nur Teile wieder speichern
 
Eine gut überlegte Frage beinhaltet meist schon die Lösung.

Deine Frage lässt viel offen, aber wenn ich unterstellen darf, dass du aus mehreren gleichartigen XML-Dokumenten die Lehrgänge extrahieren und in einem einzigen Dokument kumulieren möchtest, dann kennst du ja schon eine Lösung zum Extrahieren. Hinzufügen kannst du dann mittels einer Iteration über die einzelnen Lehrgänge und der Methode appendChild.

Magst du es selbst mal probieren?

Hoschie 2. Mär 2008 20:14

Re: Datei bearbeiten und nur Teile wieder speichern
 
Hi,

also ich habe das jetzt mal versucht umzusetzen und habe folgenden Code geschrieben

Delphi-Quellcode:
if FileExists (fnNew) then  // Prüfung ob File vorhanden
    begin
      xdNew.loadXML(fnNew); // File laden
      xdNew.appendChild(xd); // Neue daten anfügen
      xdNew.save(fnNew); // File wieder speichern
    end
    else
    begin
      xdNew.documentElement:= xd.cloneNode(True) as IXMLDOMElement; // Neues Eelemt in neuer File
      xdNew.save(fnNew); // File speichern
    end;
Das projekt kompiliert und läuft ohne Fehler durch, allerdings wird immer nur das letzte Element in der Datei gespeichert, egal ob sie neu erstellt oder geladen wurde.

Kann es sein dass
Delphi-Quellcode:
 xdNew.appendChild(xd);
nicht ganz stimmt?
Habe es auch schon mit
Delphi-Quellcode:
xdNew.documentElement.appendChild(xd);
versucht, dass gab aber eine Zugriffsverletzung.

Gruß
Hoschie

marabu 2. Mär 2008 20:27

Re: Datei bearbeiten und nur Teile wieder speichern
 
xdNew.appendChild(xd) ist ganz sicher falsch.

Du willst die childNodes von xd.documentElement hinter den childNodes von xdNew.documentElement einfügen - und zwar in einer Schleife.

Mach mal, während ich ein Bad nehme.

Hoschie 2. Mär 2008 20:49

Re: Datei bearbeiten und nur Teile wieder speichern
 
Hmmm,

aber ich habe in der Variablen xd
Delphi-Quellcode:
xd:=u.selectSingleNode('/root/data/Lehrgang');
schon das Element Lehrgang drin (oder?). Das will ich jetzt nur noch anhängen. Die Zieldatei sieht im Moment so aus
Delphi-Quellcode:
<root>
  <data>
    <Lehrgang></Lehrgang> // hier sollen die anderen angehängt werden.
  </data>
</root>
Aber jetzt bade mal in Ruhe, dass hast du dir verdient :mrgreen: :thumb:
Für mich ist wohl jetzt auch erstmal Feierabend, meine Frau schaut schon so merkwürdig.

Gruß
Hoschie

Hoschie 3. Mär 2008 20:20

Re: Datei bearbeiten und nur Teile wieder speichern
 
Moin Moin,

ich habs rausgefunden. Und geholfen hat mir dabei zusätzlich zu marabus sehr guten Anregungen ein wiederholtes, intensives Lesen, des XML-Tutorials.

Mein Code:
Delphi-Quellcode:
try
    fnNew:=('c:\Scan.xml'); // Datei zum speichern
    u:=GetXMLDocument(WebBrowser1.Document); // XML Quelle
    xd:=u.selectSingleNode('/root/data/Lehrgang'); // Benötigtes Element
    xdNode:=xd.cloneNode(True) as IXMLDOMElement;; // wichtig !!
    xdNew:= ComsDOMDocument.Create;

    if not FileExists (fnNew) then // erstellen File
    begin
      xdNew.loadXML('<?xml version="1.0"?><root></root>');
      xdNew.documentElement.appendChild(xdNode); // hier hakte es
      xdNew.save(fnNew);
    end
    else
    begin
      xdNew.load(fnNew);
      xdNew.documentElement.appendChild(xdNode); // an bestehende Datei anhängen
      xdNew.save(fnNew);
    end;
  except
  if FileExists('C:\Log.txt') then / LogFile zur Sicherheit
    begin
    AssignFile(log, 'C:\Log.txt');
    Append(log);
    Write(log,(Edit1.Text+chr(13)+chr(10)));
    CloseFile(log);
    end
  else
    begin
    AssignFile(log, 'C:\Log.txt');
    ReWrite(log);
    Write(log,(Edit1.Text+chr(13)+chr(10)));
    CloseFile(log);
    end;
  end;
Damit läuft es schon mal so, wie es soll. Jetzt werde ich da mal ein paar Testläufe mit machen um zu sehen wie es mit der Speicherverwaltung ist. Ich weiss noch nicht so recht, ob ich nicht noch irgendwas wieder freigeben muss.

Gruß
Hoschie

marabu 4. Mär 2008 18:50

Re: Datei bearbeiten und nur Teile wieder speichern
 
Hallo Hoschie,

Glückwunsch zur deiner eigenen Leistung. Steckt da in jedem Dokument immer nur ein Lehrgang?

Hier noch ein paar versteckte Anregungen:

Delphi-Quellcode:
const
  FN_LOG = 'log.txt';
  XML_TEMPLATE = '<?xml version="1.0"?><root></root>';

procedure WriteLog(const msg: string);
var
  log: TextFile;
begin
  AssignFile(log, FN_LOG);
  if FileExists(FN_LOG)
    then Append(log)
    else Rewrite(log);
  WriteLn(log, DateTimeToStr(Now), #9, msg);
  CloseFile(log);
end;

function LoadXml(xd: IXMLDOMDocument; const fn: TFileName): Boolean;
begin
  if FileExists(fn)
    then Result := xd.load(fn)
    else Result := xd.loadXML(XML_TEMPLATE);
end;


// ...
begin
  // ...
  if LoadXml(xdNew, fnNew) then
  begin
    xdNew.documentElement.appendChild(xdNode);
    xdNew.save(fnNew);
  end else Log(Edit1.Text);
  // ...
end;
Getippt und nicht getestet.

Freundliche Grüße

Hoschie 4. Mär 2008 19:19

Re: Datei bearbeiten und nur Teile wieder speichern
 
Moin und Danke,

zur Frage: ja, in jeder Datei ist nur ein Element Lehrgang drin und innerhalb des Elementes sind dann mehrere Childs.

Es läuft auch soweit, recht gut, nur nach unbestimmter Zeit bleibt er hängen. Ich habe dann versucht, das so zu machen, dass ich den Speicher der Variablen dann mit free wieder freigebe, allerdings kennt er das mal wieder nicht und in der MSXML_TLB habe ich dazu auch nichts gefunden. Geht das auch mit Release ? Oder woran könne das sonst noch liegen ?

Die versteckten Anregungen sind klasse, vereinfacht vieles. ;-)

Gruß
Hoschie

marabu 4. Mär 2008 19:29

Re: Datei bearbeiten und nur Teile wieder speichern
 
Wenn du glaubst, dass dir der Speicher zuläuft, dann solltest du ein Werkzeug wie z.B. Hier im Forum suchenMemCheck einsetzen.

Hoschie 5. Mär 2008 09:12

Re: Datei bearbeiten und nur Teile wieder speichern
 
Also ich habe nach 128 aufgerufenen XML Seiten so an die 260.000 Kb gemäß dem TaskManager, da ist es ja kein wunder, dass die Anwendung sich irgendwann aufhängt. Ich befürchte, dass ich irgendwie das WebBrowser Dokument wieder freigeben muss, bevor ich erneut darauf zugreife. Nur wie weiss ich noch nicht. Irgendwelche Tipps ?

Ich werde heute Abend mich mal an MemCheck ranwagen.

Kann ich WebBrowser so freigeben :
Delphi-Quellcode:
WebBrowser1.Document.free
und ihn dann gleich wieder erneut aufrufen oder muss das anders aussehen ?

Gruß
Hoschie

marabu 5. Mär 2008 09:33

Re: Datei bearbeiten und nur Teile wieder speichern
 
Moin Hoschie,

wenn du größere Dokumente geladen hast, dann belegt das aufgebaute DOM natürlich reichlich Speicher. Sobald du ein neues Dokument lädst, wird dieser Speicher aber automatisch wieder freigegeben. Du selbst kannst das mit WebBrowser.Navigate('about:blank') veranlassen.

Von dir verwendete Automationsobjekte (COM) werden automatisch freigegeben, sobald sie nicht mehr verwendet werden. Du kannst die vorzeitige Freigabe erzwingen, indem du sie einfach auf NIL setzt. Free() dient der Freigabe von Delphi-Objekten.

Freundliche Grüße

Hoschie 5. Mär 2008 09:54

Re: Datei bearbeiten und nur Teile wieder speichern
 
Dadurch das ich ja gleich nach der Abbarbeitung die nächste Webseite aufrufe habe ich ja keine Möglichkeit den Speicher des Dokumentes mit aufruf der Seite about:blank freizugeben. Aber wenn alles automatisch freigegeben wird, wie erkläre ich mir dann den horenden Speicherbedarf, der mit jeder aufgrufenen Seite anwächst.

Gruß
Hoschie

Bernhard Geyer 5. Mär 2008 10:01

Re: Datei bearbeiten und nur Teile wieder speichern
 
Zitat:

Zitat von marabu
Wenn du größere Dokumente geladen hast, dann belegt das aufgebaute DOM natürlich reichlich Speicher. Sobald du ein neues Dokument lädst, wird dieser Speicher aber automatisch wieder freigegeben. Du selbst kannst das mit WebBrowser.Navigate('about:blank') veranlassen.

Von dir verwendete Automationsobjekte (COM) werden automatisch freigegeben, sobald sie nicht mehr verwendet werden. Du kannst die vorzeitige Freigabe erzwingen, indem du sie einfach auf NIL setzt. Free() dient der Freigabe von Delphi-Objekten.

Theoretisch ja, praktisch hat die Implementierung im IE bezüglich Interfaces viele Fehler so das man hier (durch eigene Tests herausfinden welche) an diversen Stellen vor dem setzen auf nil einfach mal ein _Release einfügen muss um um das Problem zu löse. Jedoch schön alles mit try...except absichern da z.B. der IE 7 hier weniger Fehler hat als z.B. der IE 6 und man sonst bei einem Update das hier Fehler behebt sonst probleme bekommt.

Ich vermute mal das IE-Intern Objekte gegenseitig Interface-Zeiger halten so das hier eine "Deadlock"-Situation (ich glaube es gibt auch einen gebräuchlicheren Begriff) vorliegt.

himitsu 5. Mär 2008 10:05

Re: Datei bearbeiten und nur Teile wieder speichern
 
Zitat:

Zitat von marabu
Sobald du ein neues Dokument lädst, wird dieser Speicher aber automatisch wieder freigegeben. Du selbst kannst das mit WebBrowser.Navigate('about:blank') veranlassen.

also, TWebBrowser verwendet ja den IE und bei mir hat der IE ein Speicherleck ... wenn ich im IE selber viele Seiten hintereinander lade, dann müllt der auch so den RAM zu ;(

Dagegen hilft hier nur IE beenden und neu starten.

Falls die IE-Instanz nur vom TWebBrowser genutzt wird, dann sollte es vermutlich helfen, wenn man diesen freigibt (WebBrowser.Free) und dann neu erstellt (WebBrowser := TWebBrowser.Create) ... dann müßte ja hoffentlich auch die speicherfressende IE-Instannz gelöscht/feigegeben werden? :stupid:

Hoschie 5. Mär 2008 11:19

Re: Datei bearbeiten und nur Teile wieder speichern
 
Es wäre ja schon von Vorteil, wenn er den reservierten Bereeich nur überschreibt und nicht ständig erweitert. Ich werde das heute Abend mal antesten und dann melden.

Gruß
Hoschie

marabu 5. Mär 2008 11:24

Re: Datei bearbeiten und nur Teile wieder speichern
 
Hallo,

ich habe schon viele Threads in der DP zum Thema TWebBrowser und IE gesehen - sie hatten oft eines gemeinsam: Die falsche Darstellung der Beziehung zwischen dem Webbrowser Control und dem Internet Explorer. Das visuelle Herzstück des modular aufgebauten IE ist das Webbrowser Control und nicht umgekehrt. Der IE ist ein Host für das WB Control, so wie viele andere Browser (nicht FireFox oder Opera) auch.

Ich habe zu Zeiten von IE5 damit begonnen das Control in einem Projekt zu verbauen. Speicherlecks beim IE habe ich nie gesucht, es gab bis heute keinen Grund dazu. Ich will damit nicht behaupten, dass es diese Lecks nicht gäbe, alleine mir sind bisher keine aufgefallen.

Ich bin auch fest davon überzeugt, dass die Ursache für Speicherlecks im Programm von Hoschie zuerst in seinem eigenen Code gesucht werden muss.

Freundliche Grüße

Hoschie 5. Mär 2008 11:42

Re: Datei bearbeiten und nur Teile wieder speichern
 
Was durchaus sehr wahrscheinlich ist und ich das ganze nicht absprechen möchte, weil ich dafür vieeeel zu wenig Ahnung habe. Es sah für mich nur eben nach einem direktem Zusammenhang mit dem aufrufen der Seiten auf, weil die Speichermenge in dem Moment stieg, als er die neue Seitee geladen hat, Aber ich werde versuchen das ganze möglichst einzugrenzen mit dem MemCheck.

Trotzdem bin allen Postern hier sehr dankbar für die Hilfe :mrgreen:


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:09 Uhr.
Seite 1 von 2  1 2      

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