Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   XML (https://www.delphipraxis.net/46-xml/)
-   -   Delphi XML Daten in DB importieren (https://www.delphipraxis.net/128090-xml-daten-db-importieren.html)

ryLIX 23. Jan 2009 21:36


XML Daten in DB importieren
 
Hallo DPler :hi:

Ich sitze grade vor einem Problem was mir üble Kopfschmerzen bereitet.
Ich muss ca. 450.000 Zeilen XML Daten in eine DB haben.
Es sollte eine Embedded DB sein. Welche is mir im Moment wurscht (SQLite, Firebrid etc.).

Die Daten haben folgende Struktur:

XML-Code:
<ROOT>
<Node value="E31">
      <Node value="ABGB-C02" />
      <Node value="ABGZ-C01" />
      <Node value="ASC5-C01" />
      <Node value="ASC5-C06" />
      <Node value="DSC-C01" />
      <Node value="DWA3-C25" />
      <Node value="DWA4-C27" />
      <Node value="EDC3-C00" />
      <Node value="EDC3P-C25" />
      <Node value="EKM-C00" />
      <Node value="EKM-C01" />
      <Node value="EKM-C25" />
      <Node value="EML-C01" />
      <Node value="EWS-C01" />
      <Node value="EWS-C02" />
      <Node value="GM2-C25" />
      <Node value="LKM2-C25" />
      <Node value="LSM-C25" />
      <Node value="ZAE2-C03" />
      <Node value="ZAE2-C05" />
    </Node>
<--!Viele Subnodes weiter-->
</ROOT>
Wobei das nur ein SubNode ist.
Es gibt noch eine andere Variante (das ist der Aufbau der meisten Daten(~90%)):

XML-Code:
<ROOT>
<E31ASC5-C06 value="ASC5-C06">
    <FSW value="MRA_TAKTUNG">
      <PSW value="aktiv"/>
      <PSW value="nicht_aktiv"/>
    </FSW>
    <FSW value="LASTBEREICHSKENNFELD">
      <PSW value="aktiv"/>
      <PSW value="nicht_aktiv"/>
    </FSW>
    <FSW value="SCHLUPFSCHWELLENOFFSET">
      <PSW value="aktiv"/>
      <PSW value="nicht_aktiv"/>
    </FSW>
    <FSW value="GETRIEBE">
      <PSW value="automatik"/>
      <PSW value="handschaltung"/>
    </FSW>
    <FSW value="BMR_TYP">
      <PSW value="typ_1"/>
      <PSW value="typ_2"/>
      <PSW value="typ_3"/>
    </FSW>
    <FSW value="AMR_TYP">
      <PSW value="typ_1"/>
      <PSW value="typ_2"/>
      <PSW value="typ_3"/>
    </FSW>
    <FSW value="SCHLUPFBANDMODIFIKATION">
      <PSW value="nicht_aktiv"/>
      <PSW value="absenkung_0.5_km/h"/>
    </FSW>
    <FSW value="MRAGRENZ">
      <PSW value="wert_01"/>
    </FSW>
    <FSW value="KURVENLOGIK">
      <PSW value="typ_1"/>
      <PSW value="typ_2"/>
      <PSW value="typ_3"/>
    </FSW>
  </E31ASC5-C06>
<--!Viele Subnodes weiter-->
</ROOT>
Ich hatte erst versucht die Daten so zu nutzen aber das ist absolut inakzeptabel von der Geschwindigkeit her.
Man meint das die Daten aus dem Web geladen werden und nicht direkt von der Platte :?

Jetzt suche ich eine Möglichkeit diese Daten möglichst einfach in eine Datenbank zu bringen.
Erste versuche mit Access sind kläglich gescheitert.
Insgesamt Teilt sich die Datenmenge auf 18 Solcher Dateien auf.
Die zentrale Liste hat das zu erst gepostete Format die anderen 17 das zweite Format.
Wie kann ich nun das ganze am schnellsten in Tabellen bringen?

Mit den <Node> Elementen habe ich bisher ein Treeview gefüllt.
Das wollte ich auch gern bei behalten.
Für die Bereiche <FSW> sowie <PSW> ist jeweils eine ListBox vorgesehen.
Hier wäre es optimal wenn die ID der FSW mit dem Index in der Listbox übereinstimmt damit ich darüber die passenden <PSW> Elemente finde.

Als XML Parser habe ich ADOM (OpenXML) im einsatz.
Damit komme ich auch gut klar aber die Geschwindigkeit ist unzumutbar für Anwender.

Ich wäre dankbar wenn mir jemand etwas Hilfe bei der Umsetztung geben könnte da XML immer noch nich so ganz meins ist :stupid:

haentschman 24. Jan 2009 07:18

Re: XML Daten in DB importieren
 
Hallo...

ich benutze für so etwas SimpleXML von den Jedis. Dann schreibe ich mir passend zu den Daten eine procedure, welche die Daten in die Datenbank einträgt (eventuell noch mit Informationen welche nicht im XML stehen).

...das ist aber auch keine schnelle Variante. Wie oft mußt du die XML einlesen ?. Ich brauche, da das Einlesen / Konvertieren in 2 Schleifen abläuft, für 40000 Datensätze ca. 20-30 Sekunden.

:hi:

PS: ich bin bekennender Firebird Fan...deshalb dieses als Empfehlung :P

ryLIX 24. Jan 2009 08:00

Re: XML Daten in DB importieren
 
Wie lange das braucht ist mir egal.
Da ich die Daten nur einmal da rein bringen muss danach kann ich die Updates direkt machen.

Ich werde mir das mit den Jedis mal anschauen danke für den Tipp.
Hast du eventuell noch ne kleine Anleitung zu dem ganzen damit ich mich mal einlesen kann?
Habe bisher die Jedis nicht genuzt.

haentschman 24. Jan 2009 08:11

Re: XML Daten in DB importieren
 
...ich zeige dir einfach mal eine procedure :wink:
Delphi-Quellcode:
// Import XML Gebührenordnung
procedure TDMDB.XMLImportGE;
var
  AnzahlDS: Integer;
  A: Integer;
  I: Integer;
  Inhalt: TStringList;
begin
  Inhalt:= TStringList.Create;
  try
    JvSimpleXML1.FileName:= InstallPfad + 'GE.xml';
    AnzahlDS:= JvSimpleXML1.Root.Items.Item[1].Items.Count;
    if Start then
      begin
        Splash.JvXPProgressBar1.Max:= AnzahlDS;
        Splash.JvXPProgressBar1.Position:= 0;
        Splash.JvLabel1.Caption:= 'Import GebüH...';
      end;
    Splash.JvXPProgressBar1.Refresh;
    Splash.JvLabel1.Refresh;
    for A:= 0 to AnzahlDS -1 do
      begin
        try
          Inhalt.Clear;
          Splash.JvXPProgressBar1.Refresh;
          for I:= 0 to 2 do
            begin
              Inhalt.Add(JvSimpleXML1.Root.Items.Item[1].Items.Item[A].Items.Item[I].Value);
            end;
          ZQueryDiv.SQL.Text:= 'insert into GEBUH (GRUPPE,UNTERGRUPPE,TEXT,GEBUHID,LEISTUNG,NUMMER,ICON) values ';
          ZQueryDiv.SQL.Add('(:Gruppe,:Untergruppe,:Text,:GebuhID,:Leistung,:Nummer,:Icon)');
          ZQueryDiv.ParamByName('Gruppe').Value:= A+2;
          ZQueryDiv.ParamByName('Untergruppe').Value:= 1;
          ZQueryDiv.ParamByName('Text').Value:= Inhalt.Strings[2] + '  ' + Inhalt.Strings[1];
          ZQueryDiv.ParamByName('GebuhID').Value:= StrToInt(Inhalt.Strings[0]);
          ZQueryDiv.ParamByName('Leistung').Value:= Inhalt.Strings[1];
          ZQueryDiv.ParamByName('Nummer').Value:= Inhalt.Strings[2];
          ZQueryDiv.ParamByName('Icon').Value:= 2;
          ZQueryDiv.ExecSQL;
        except
          FehlerCode:= 'E422';
          Fehlerstatus:= False;
          Fehlertext:= 'Import der GebüH fehlgeschlagen. ';
          raise;
        end;
        if Start then Splash.JvXPProgressBar1.Position:= A;
        Splash.JvXPProgressBar1.Refresh;
      end;
  finally
    Inhalt.Free;
  end;
  try
    if FileExists(InstallPfad + 'GE.xml') then DeleteFile(InstallPfad + 'GE.xml');
  except
    FehlerCode:= 'E421';
    Fehlerstatus:= True;
    Fehlertext:= 'Löschen der Datei GE.xml fehlgeschlagen. ';
    raise;
  end;
  FGebuH.GEBUHEinlesen;
end;
Delphi-Quellcode:
Inhalt.Add(JvSimpleXML1.Root.Items.Item[1].Items.Item[A].Items.Item[I].Value);
...mit diesem Part mußt du dann etwas experimentieren entsprechend der Struktur deiner XML.

Der Ablauf ist im Prinzip folgender:
- 1. Schleife A -- Anzahl der Datensätze / Nodes
- 2. Schleife I -- Schreibt die Values des Nodes in eine StringList, I(MAX) entspricht der Menge der Values in der StringList (in diesem Falle 2..bei dir vieleicht anders)
- 3. Insert in DB mit den Werten der StringList
....usw.

viel Spaß... :wink:

ryLIX 24. Jan 2009 08:19

Re: XML Daten in DB importieren
 
Danke dir.
Das sieht relativ einfach aus.
Hatte schon den Verdacht das mich das einige graue Haare kosten würd aber damit sieht es im Moment sehr einfach aus.

:dp:

Herzlichen Dank :cheers:

haentschman 24. Jan 2009 08:28

Re: XML Daten in DB importieren
 
PS: du kannst die Nodes in der XML auch anders identifizieren. Schaust du einfach was JvSimpleXML dir an Propertys bietet. Für mich bot sich ITEMS an, da ich das dann gut über den Index in der Schleife verarbeiten kann.

PS1: den ganzen Visualisierungskram kannst du ja weg lassen... :P

:hi:

ryLIX 24. Jan 2009 08:29

Re: XML Daten in DB importieren
 
Ok werd mal reinschauen :)

Muss erstmal die Jedis Installieren :)

ryLIX 24. Jan 2009 11:44

Re: XML Daten in DB importieren
 
So das mit dem Items identifizieren is mir nun klar.
Geht über Item[index] oder ItemNamed[name].

Aber wie komme ich an die Attribute des Items?
Die Methodenliste gibt da nix her :(

haentschman 24. Jan 2009 11:58

Re: XML Daten in DB importieren
 
ich denke daß du...

Item[x].Value meinst. Das repräsentiert den Wert deines ItemNamed['blabla']
oder
dein ItemNamed['blabla'] hat wieder Items.Item[x].Value je nach Verzweigung deiner Vorlage.

:hi:

ryLIX 24. Jan 2009 12:41

Re: XML Daten in DB importieren
 
Hatte einen test gemacht mit einem Memo.
Delphi-Quellcode:
  OpenDialog1.Execute();
  if OpenDialog1.FileName <> '' then
  begin
      JvSimpleXml1.FileName := OpenDialog1.FileName;
      for I := 0 to JvSimpleXML1.Root.Items.Item[0].Items.Count - 1 do
        Memo1.Lines.Add(JvSimpleXML1.Root.Items.Item[0].Items.Item[I].Value)
  end;
Nur bleibt das Memo leer :wiejetzt:

Edit:
Er findet auf jeden Fall Items da I > 0 ist ;)
Hab ich grad noch mal im Debug gecheckt.

Noch mal Edit:
Nu passiert was :idea:
Aber die ausgelesenen Strings sind leer :wiejetzt:

Haha rate mal ein Edit:
So gehts:
Delphi-Quellcode:
var
  I: Integer;
begin
  OpenDialog1.Execute();
  if OpenDialog1.FileName <> '' then
  begin
      JvSimpleXML1.LoadFromFile(OpenDialog1.FileName);
      for I := 0 to JvSimpleXML1.Root.Items.Item[0].Items.Count - 1 do
        Memo1.Lines.Add(JvSimpleXML1.Root.Items.Item[0].Items.Item[I].Properties.Value('value'));
  end;
end;

haentschman 24. Jan 2009 16:10

Re: XML Daten in DB importieren
 
ah jetzt ja.... :gruebel:
Zitat:

.Properties.Value('value'))
...habe ich noch nicht gebraucht. Liegt wahrscheinlich an der Struktur der XML. Gut zu wissen, was es noch so gibt :wink:

ryLIX 24. Jan 2009 16:28

Re: XML Daten in DB importieren
 
Jetzt muss ich nur noch die embedded DB zum laufen bekommen -.-
Mal sehen wie lang ich dafr brauch :roll:

haentschman 24. Jan 2009 16:37

Re: XML Daten in DB importieren
 
fbclient.dll
firebird.conf
firebird.msg
icudt30.dll
icuin30.dll
icuuc30.dll

...diese Dateien ins Anwendungsverzeichnis
- DB mit z.B. IBExpert erstellen
- DB in beliebiges Verzeichnis
- Connection abhängig von Zugriffskomponenten
Tipps für Zeos:
- Host muß ein Leerstring sein ''
- User und Paßwort zuweisen (Standard: SYSDBA / masterkey)
- Database: lokaler Ordner wo die Datenbank liegt.

:hi:

ryLIX 24. Jan 2009 17:13

Re: XML Daten in DB importieren
 
Ne ich hab mich für DISQLite3 und SQLite3.dll entschieden :)
Der Fehler war die ganze Zeit im Statement habs nur vor blindheit nich gesehen :oops:

haentschman 24. Jan 2009 17:22

Re: XML Daten in DB importieren
 
...viel Spaß beim Entdecken der unbekannten Möglichkeiten. :P

ryLIX 24. Jan 2009 17:26

Re: XML Daten in DB importieren
 
Unbekannt sind die nicht :)
Hab sqlite3 schon in einem .Net Projekt im Einsatz :)

Aber die Geschwindigkeit wird schön.

Muss ich nur noch die Routine für den Import der anderen Daten schreiben.
Hab gesehen das die JVCL ein DBTreeView liefert :)
Muss ich das auch nimmer suchen :stupid:

Danke nochmal für deine Hilfe :)

haentschman 24. Jan 2009 17:32

Re: XML Daten in DB importieren
 
Zitat:

Hab gesehen das die JVCL ein DBTreeView liefert
...benutze ich auch gern...schmerzfrei wenn man die Datenfelder entsprechend anlegt.
...hier habe ich mal erklärt worauf es ankommt.
kurze Erklärung
:hi:

ryLIX 24. Jan 2009 18:26

Re: XML Daten in DB importieren
 
Ui du bist mein Held heute :)
Im Hintergrund rattert die Festplatte weil durch deine Hilfe das ganze sehr einfach geworden ist :)
Ich hoffe das ich das ganze dann heut abend noch in die DB bekomme :D
Dann hab ich nen großen vortschritt gemacht was Wissen und Projekt angeht :) :dp: :dp:

haentschman 24. Jan 2009 18:40

Re: XML Daten in DB importieren
 
...und ich habe meine guten Taten für dieses Jahr weg... :mrgreen: :cheer:

ryLIX 24. Jan 2009 18:48

Re: XML Daten in DB importieren
 
Und ich tu auch noch eine :)

Hier die Routine die ich nun zusammen gestellt habe.
Falls jemand das gleiche bzw ein ähnliches Problem hat kann er sich daran orientieren :)

Delphi-Quellcode:
procedure TForm2.xml_batch(FileName: string);
var
  tblName: string;
  FSW: string;
  B: Integer;
  I: Integer;
  PSW: string;
  A: Integer;
begin
  JvSimpleXML1.LoadFromFile(FileName);
  for I := 0 to JvSimpleXML1.Root.Items.Item[0].Items.Count - 1 do
  begin
    tblName := '';
    PSW := '';
    FSW := '';
    tblName := StringReplace(JvSimpleXML1.Root.Items.Item[0].Items.Item[I].Name, '-', '_', [rfReplaceAll]);
    DISQLite3db.Execute16('CREATE TABLE [' + tblName + '] ([ID] INTEGER NOT NULL PRIMARY KEY,[FSW] TEXT NOT NULL,[PSW] TEXT NULL,[COMMENT] TEXT NULL)');
    for A := 0 to JvSimpleXML1.Root.Items.Item[0].Items.Item[I].Items.Count - 1 do
    begin
      FSW := JvSimpleXML1.Root.Items.Item[0].Items.Item[I].Items.Item[A].Properties.Value('value');
      for B := 0 to JvSimpleXML1.Root.Items.Item[0].Items.Item[I].Items.Item[A].Items.Count - 1 do
      begin
        PSW := PSW + JvSimpleXML1.Root.Items.Item[0].Items.Item[I].Items.Item[A].Items.Item[B].Properties.Value('value') + #10;
      end;
      DISQLite3db.Execute16('INSERT INTO ' + tblName + ' VALUES (NULL,"' + FSW + '","' + PSW + '", "")');
    end;
  end;
end;
Noch eine kurze anmerkung:
Ich habe wie schon erwähnt SQLite3 im einsatz.
Code:
[ID] INTEGER NOT NULL PRIMARY KEY
Bewirkt bei SQLite3 ein Integerfeld mit Autoincrement :)

haentschman 24. Jan 2009 18:59

Re: XML Daten in DB importieren
 
Zitat:

Mit den <Node> Elementen habe ich bisher ein Treeview gefüllt.
Das wollte ich auch gern bei behalten.
Wenn ich richtig gesehen habe schreibst du nur die XML in die DB. Wenn du den JvDBTreeView benutzen möchtest solltest du dir beim Import in die DB die benötigten Felder für Gruppe und Untergruppe mit anlegen und die Positionen deiner Knoten eintragen.
...siehe kurze Erklärung in #17. Weil ohne die 2 Integer Felder kann der DBTreeView den Baum nicht darstelllen.

PS: für JvDBTreeview1.MasterField kannst du auch dein ID Feld benutzen, da es ja eh eine laufende Nummer darstellt.

:hi:

ryLIX 24. Jan 2009 19:20

Re: XML Daten in DB importieren
 
Das ist nur die Routine für den zweiten XML abschnitt im eingangs Posting ;)

Die TreeView Tabelle hat ein ID Feld und ein Parent_ID Feld.
Root = 0
E31 = 1
usw.
So hat E31 Parent_ID 0
Und alle unterbereiche von E31 Parent_ID = 1

Dürfte so gehen oder?
Hab den Link erst gesehen nach dem die Daten in der DB waren :stupid:
Aber das dauert 20sec die Daten neu zu laden falls es nicht passt.

haentschman 24. Jan 2009 19:30

Re: XML Daten in DB importieren
 
Zitat:

Dürfte so gehen oder?
...hast es verstanden :thumb:

ryLIX 24. Jan 2009 19:44

Re: XML Daten in DB importieren
 
Hehe und das ohne vorher zu wissen das es so sein muss :mrgreen:
Selbstständiges denken liegt mir irgendwie. Vielleicht war ich deswegen nich beim Bund :corky:

Dann hab ich nun alles zusammen und werd den Thread als gelöst markieren :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:06 Uhr.

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