Alcinoe TALXmlDocument - parsen einer langen XML-Datei

Rund um die LCL und andere Komponenten
Antworten
Nouba
Beiträge: 4
Registriert: Do 14. Apr 2011, 02:51

Alcinoe TALXmlDocument - parsen einer langen XML-Datei

Beitrag von Nouba »

Hallo liebe Mitleser,

vorweg - ich bin noch nicht so fit, was Object-Pascal angeht.

Zu meiner Problembeschreibung: Ich lade mir von http://www.ecb.europa.eu/stats/eurofxre ... f-hist.xml" onclick="window.open(this.href);return false; die kompletten Euro-Wechselkurse in einen MemoryStream und verwende zum Parsen des so erhaltenen XML-Dokuments die TALXmlDocument-Komponente von Alcinoe, was recht bequem zu realisieren ist. Leider musste ich dabei feststellen, dass bei eben diesem grossen Dokument (~3mb) nicht der komplette Inhalt bearbeitet wird, sondern bei ca. 14000 bearbeiteten Elementen Schluss ist - dummerweise auch noch ohne Fehlermeldung. Der Download ist komplett (habe den MemoryStream in eine Textdatei gespeichert) und die Daten stellen auch gültiges XML dar (ebenso getestet). Hier mal die relevanten Teile des Codes.

Code: Alles auswählen

procedure TMainForm.StartDownloadClick(Sender: TObject);
var
  ms: TmemoryStream;
begin
  ms := TMemoryStream.Create;
  try
    // Indy-IdHTTP-Komponente mit URL aus Kombifeld füttern und Download
    // im MemoryStream ms ablegen
    with UrlSelectCombo do
      IdHTTP1.Get(string(Items.Objects[ItemIndex]), ms);
    // ms.Position := 0;  {hilft leider nicht}
    // das Parsen wird sofort eingeleitet, wobei ich eher erwartet hätte
    // Active auf True setzen zu müssen oder eine Methode wie parseXML
    // aufrufen zu müssen
    XMLRates.LoadFromStream(ms);
  finally
    ms.Free;
  end;
end;
 
procedure TMainForm.XMLRatesParseStartDocument(Sender: TObject);
begin
  with Sqlite3Dataset1 do
  begin
    // Tabelle rates der SQLite3-DB löschen
    ExecSQL('delete from rates;');
    //SQLList für den Import vorbereiten
    SQLList.Clear;
    SQLList.Add('begin;');
  end;
end;
 
procedure TMainForm.XMLRatesParseEndDocument(Sender: TObject);
begin
  with Sqlite3Dataset1 do
  begin
    SQLList.Add('commit;');
    // SQL-Inserts ausführen
    ExecSQLList;
    // Daten erneut einlesen
    RefetchData;
  end;
end;
 
procedure TMainForm.XMLRatesParseStartElement(Sender: TObject;
  const AName: TALXMLString; const Attributes: TStrings);
var
  cur: string = '';   // für das Währungskürzel
  rate: string = '';  // für den Wechsel-Faktor
  sql: string = '';
  s: String;
  i: integer = 0;
begin
  // wird ein Cube Element geparst?
  if AName = 'Cube' then
  begin
    with Attributes do
    begin
      // enthält es ein Attribute time?
      i := IndexOfName('time');
      if i = 0 then
      begin
        // Zeitwert als string ablegen - Format: YYYY-MM-DD
        FTime := ValueFromIndex[i];
        Exit;
      end;
      // ist ein currency Attribut vorhanden
      i := IndexOfName('currency');
      if i >= 0 then
      begin
        // dann den Wert festhalten
        cur := ValueFromIndex[i];
        i := IndexOfName('rate');
        if i >= 0 then
        // ... und den Faktor rate auslesen - (Punkt ist Dezimaltrennzeichen)
        begin
          rate := ValueFromIndex[i];
          // string FTime in Datum konvertieren und dieses als String mit
          // Punkt als Dezimaltrennzeichen in s ablegen
          Str(ScanDateTime('YYYY-MM-DD', FTime), s);
          // SQL-Anweisung erzeugen
          sql := 'insert into rates(time,cur,rate) values(%s,''%s'',%s);';
          // ... mit Werten bestücken
          sql := Format(sql, [s, cur, rate]);
          // und der SQLList hinzufügen
          Sqlite3Dataset1.SQLList.Add(sql);
        end;
      end;
    end;
  end;
end;
Meine Frage ist, ob jemand die Ursache für das Verhalten kennt - oder besser noch - weiß oder Tipps geben kann, wie das komplette XML-Dokument geparst werden kann. Alternativ würde ich dafür auch auf einen anderen Sax-Parser umsteigen. Mir fehlt es aber an einem Hinweis, wie z. Bsp die libxml2 bzw. sax aus fcl-xml dafür verwendet werden kann. Alle meine Versuche mit fpc-xml sind bisher kläglich gescheitert.

schöne Grüsse aus Berlin
Nouba

Antworten