Home » Tutorials » Datenspeicherung » ThaXML-Library

ThaXML-Library

Laden

Jetzt gehen wir den umgekehrten Weg und starten gleich mit der Prozedur des Formulars, wenn man auf „laden“ klickt.

procedure TForm1.btLoadClick(Sender: TObject);
var root, xml: TXMLTag;
begin
  // Wurzel-Objekt erzeugen
  root := TXMLTag.Create(nil);

  // Datei einlesen
  if XMLParser.ParseXMLFile('config.xml', root) then begin

    // Tag "xml" holen
    xml := root.Items.Tags['xml'];
    if Assigned( xml) then

      // Einstellungen laden
      Einst.LoadFromXML(xml);

    // Formular updaten
    UpdateView;
  end;

  // Speicher freigeben
  root.Free;
end;

Diesmal kommt der sog. „root“-Tag ins Spiel. Dieses TXMLTag-Objekt existiert nicht in der Datei. Allerdings wird in dieses Objekt der Inhalt der Datei eingelesen. Es steht sozusagen „außerhalb“ der Datei. Da dieses Objekt keinen Besitzer hat, wird der Parameter einfach auf nil gesetzt. In der nächsten Zeile wird die Datei geparst. Sollte alles gut gehen, ist der Inhalt der Datei nun als TXMLTags im Speicher. Wenn wir das Listing der Datei anschauen, sehen wir, dass die Datei auf oberster Ebene nur den Tag „xml“ hat (wie es die Regeln vorschreiben). Da alle anderen Tags unterhalb liegen, müssen wir uns eine Referenz auf „xml“ holen, welches ein „Kind“ von „root“ ist. Alle untergeordneten Elemente speichert ein TXMLTag in dem Property „Items“. Dieses ist vom Typ TXMLItems. Dieses Objekt bietet verschiedene Möglichkeiten auf die Tags oder Textstellen zuzugreifen.
Auf Tags können Sie anhand ihres Namens über das gleichlautende Property zugreifen. Nun veranlassen wir das Objekt „Einst“, sich zu laden. Sie werden merken, dass das Laden weit umfangreicher als das Speichern ausfällt, wenn man sämtliche Fehlerüberprüfungen durchführt. Außerdem muss man sich erst immer eine Referenz holen. So sieht die ganze Prozedur aus:

procedure TEinstellungen.LoadFromXML(AParent: TXMLTag);
var i: integer;
  p: TXMLTag;
  t: TTest;
begin
  // Liste löschen
  while List.Count > 0 do begin
    t := List[0];
    t.Free;
    list.Delete( 0);
  end;

  // checked laden
  p := AParent.Items.Tags['checked'];
  if Assigned(p) then checked := p.Value = 'true';

  // zeichenkette laden
  p := AParent.Items.Tags['zeichenkette'];
  if Assigned(p) then zeichenkette := p.Value;

  // Liste holen
  p := AParent.Items.Tags['list'];
  if Assigned(p) then
    // für jeden Tag in <liste>
    for i := 0 to p.Items.TagCount -1 do begin
      // neues TTest-Objekt erstellen
      t := TTest.create;
      // t laden
      t.LoadFromXML(p.Items.TagsByIdx[ i]);
      // t zur Liste hinzufügen
      List.Add(t);
    end;
end;

Zuallererst löschen wir die Liste, falls sich dort noch Objekt befinden. Erst holen wir uns eine Referenz auf den „checked“-Tag. Diesen fordern wir wieder über dessen Namen an. Wenn kein Tag mit diesem Namen vorhanden sein sollte, wird nil zurückgegeben, also testen wir mit „Assigned“ ob tatsächlich ein Tag gefunden wurde. Jeder TXMLTag hat das nur-lesen Property „Value“, mit dem man den Text zwischen dem Tagpaar auslesen kann. Je nach Wert wird die Variable „checked“ belegt. Ebenso wird der Tag „zeichenkette“ ausgelesen. Nun kommt die Liste an die Reihe. Nachdem wir eine Referenz geholt haben, gehen wir alle Tags der Liste durch. Das „TagCount“-Property gibt die Anzahl aller Kind-Tags an, und mit „TagsByIdx“ bekommen wir eine Referenz zurück. Diese geben wir gleich an das Objekt t: TTest weiter, so dass es sich laden kann. Das Objekt wird anschließend in die Liste gehängt.
Für das Laden der Klasse TTest wurde der Quelltext auf ein absolutes Minimum reduziert. Überprüfungen werden zur Gegendemonstration nicht durchgeführt.

procedure TTest.LoadFromXML(AParent: TXMLTag);
var i: integer;
  p: TXMLTag;
begin
  // Listen löschen
  str1.Clear;
  str2.Clear;

  // int laden
  int := StrToInt(AParent.Items.Tags['int'].Value);

  // Liste1 laden
  p := AParent.Items.Tags['liste1'];
  for i := 0 to p.Items.TagCount-1 do
    // alle Tags durchlaufen und Wert in Liste schreiben
    str1.Add(p.Items.TagsByIdx[i].Value);

  // Liste2 laden
  p := AParent.Items.Tags['liste2'];
  for i := 0 to p.Items.TagCount-1 do
    // alle Tags durchlaufen und Wert in Liste schreiben
    str2.Add(p.Items.TagsByIdx[i].Value);
end;

Auch hier löschen wir erst die alten Listen. Dann geht?s gleich weiter: Typumwandlung und Referenz werden in einer Zeile gelöst. Auch die Listen werden geladen, indem gleich das „Value“-Property angesprochen wird. Dies soll ein Negativbeispiel sein, wie man es nicht machen sollte. Bedenken Sie, Ihre Konfigurationsdatei liegt im Textformat vor, so dass theoretisch jeder daran „herumpfuschen“ kann. Sie sollten also immer überprüfen, ob ein Tag auch wirklich vorhanden ist. Ändern Sie doch selbst einmal die config.xml und laden sie im Programm. Bauen Sie absichtlich mal ein paar Fehler ein, und testen Sie das Beispielprogramm.