Zur Navigation

Monstermäßige XML-Dateien. [2]

11 Ranma (Gast)

Genau nach so etwas habe ich gesucht! Und auch mein OpenSUSE hatte es schon an Bord. Ich habe die Datei jetzt in vier kleinere Dateien zerlegt. Weiter bin ich noch nicht, aber ich bin schon gespannt, was ich damit anstellen kann. Ich hatte noch die Idee, daß sich mit MySQL vielleicht direkt machen ließe, was PHP nicht konnte. Dabei entdeckt, daß es die Möglichkeit LOAD XML INFILE ... INTO TABLE ... gibt. Das scheint aber irgendwie eine besondere Syntax in der XML-Datei zu erfordern. Mal sehen, ob ich eine passende Query hinbekomme...
Ranma

27.10.2015 23:27

12 Ranma (Gast)

Irgendwie half das auch nichts. split macht auch ungleich große Dateien, das machte es noch leichter. Aber jede der kleineren XML-Dateien legte erstmal den Texteditor lahm, trotz einfachem Farbschema. Benennt man eine .xml-Datei jedoch zur .txt-Datei um, dann verhält sie sich sofort deutlich kooperativer. Der Versuch eine der Dateien mit file() einzulesen führt trotzdem zum gleichen Fehler wie mit der großen Datei. Außer daß dieses Mal 36 Byte nicht untergebracht wurden. Die 20 Byte aus der vorherigen Fehlermeldung waren dann wohl nicht alle, die nicht untergebracht werden konnten. PHP muß den Versuch abgebrochen haben. Also hat das Aufteilen nichts gebracht.

Neue Idee: Mit fgets() innerhalb einer FOR-Schleife kann ich einige tausend Zeilen einlesen. Mit einer WHILE-Schleife bis feof() wird stattdessen der Prozessor voll ausgelastet, so daß kaum noch etwas passiert.

Innerhalb der Datei sind Einträge durch <entry> und </entry> kenntlich gemacht. Dazwischen kann sich eine unterschiedliche Anzahl an Zeilen befinden. Ein Eintrag besteht zwischen den beiden tags aus erst einer Nummer, dann den Schreibweisen im Japanischen (davon gibt es fast immer mehrere), danach Anmerkungen zwischen verschiedenen tags und schließlich Übersetzungen in eine von Eintrag zu Eintrag unterschiedliche Anzahl an anderen Sprachen. Natürlich können es pro Sprache auch mehrere Übersetzungen sein.

Mein neuer Plan ist nun, die Datei in einer WHILE-Schleife zu durchlaufen, ein Array mit fgets() aufzufüllen, aber das Array bei jeder Zeile, die </entry> enthält wieder zu leeren. Zwischen Füllen und Leeren des Arrays muß dann das Senden an die Datenbank erfolgen. In meinen bisherigen Wörterlisten hatte ich für jeweils einen Ausdruck mehrere Übersetzungen, das heißt die Einträge waren zwar mehrdeutig, aber doch klar, wie sie in die Datenbank einzutragen waren. Mit der Japanisch-Liste ist das nicht so klar, weil sie mehrfach mehrdeutig ist. Wahrscheinlich hat deswegen jeder Eintrag eine Nummer. Ich vermute jetzt, daß es im Sinne der Normalisierung angemessen wäre pro Nummer des Eintrages eine Tabelle mit den japanischen Schreibweisen, eine Tabelle mit den Übersetzungen und eine Tabelle mit sonstigen Anmerkungen (die in den meisten Fällen leer bliebe) zu haben, also insgesamt drei Datenbanktabellen?
Ranma

29.10.2015 01:42

13 Jörg Kruse

Für das Parsen von XML-Dateien hat PHP auch noch eine eigene Erweiterung, den XMLReader. Dieser liest die XML-Dateien nicht als ganzes ein, sondern als Stream. Damit sollte es dann keine derartigen Speicherprobleme geben.

Ansonsten könntest du, da du auf dem lokalen System arbeitest, auch noch den Wert für memory_limit in der php.ini erhöhen.

Edit:

die Frage bez. der Datenbanktabellen sollten wir denke ich besser in einem eigenen Thread "Datenbank-Design für Wörterbuch" (oder so ähnlich) behandeln :)

29.10.2015 14:23 | geändert: 29.10.2015 14:31

14 Ranma (Gast)

XMLReader sieht mächtig kompliziert aus. Ich habe stundenlang an der Anpassung meines Skriptes getüftelt. Mußte dafür drei Datenbanktabellen anlegen. Ich probiere es also erstmal damit. Vorerst war mein Server mit einer anderen Liste beschäftigt.

Mein Skript sieht jetzt so aus, daß für jeden XML-tag, der mehrfach vorkommen kann, ein weiteres Array existiert, in das erstmal alles hineinkommt. Dann kommen drei FOREACH-Schleifen, die alles in die drei Datenbanktabellen befördern. Die weiteren Arrays werden schließlich zusammen mit dem Haupt-Array in der WHILE-Schleife geleert.

Wahrscheinlich mache ich sowieso noch ein neues Thema, wenn ich mich daran mache, die Datenbank Woerterbuch zu normalisieren. Aber im Moment brauchte ich erstmal drei Tabellen für das Skript, sonst wäre es zu kompliziert geworden.
Ranma

30.10.2015 01:51

15 Ranma (Gast)

Auch diesem Skript habe ich noch ein set_time_limit() an den Anfang gestellt. Es läuft und zwar seit vielen Stunden. Zumindest scheint es das zu machen, was es tun soll. Ich bin mir zwar nicht sicher, ob sich am Ende alle zu verknüpfenden Informationen noch richtig einander zuordnen lassen werden, aber fast perfekt sollte zu machen sein.

In dem Skript erweist sich strip_tags() endlich mal als richtig nützlich.
Ranma

31.10.2015 02:08

16 Ranma (Gast)

Das Skript ist irgendetwas zwischen zwanzig Stunden und vierundzwanzig Stunden gelaufen. In einer der drei dadurch befüllten Datenbanktabellen sind nun über eine Millionen Einträge enthalten.

Das führte sofort zum nächsten Problem. Die Datenbank läßt sich nicht mehr exportieren. Dafür wollte ich die Exportieren-Funktion in phpMyAdmin benutzen, weil ich sonst auch garnicht wüßte wie. Aber dadurch entsteht nur noch eine 0 Byte große Datei.

Ich will die Datenbank nicht nur für eine generelle Sicherungskopie exportieren, sondern auch um sie vielleicht später mal in eine produktive Datenbank zu importieren.
Ranma

01.11.2015 01:17

17 Jörg Kruse

phpMyAdmin unterlieg beim Im- und Export von Datenbanken Beschränkungen, die auch durch die Limits von PHP bedingt sind.

Für das Exportieren von größeren Datenbanken eignet sich das Konsolen-Tool mysqldump, z.B.:

mysqldump -u <user> -p -D <datenbank> > dump.sql

(<user> und <datenbank> entsprechend ersetzen)

Nach dem Enter muss man noch das Passwort von <user> eingeben und danach warten bis das Tool fertig ist, was man daran sieht, dass der Prompt erscheint (kann je nach Größe der Datenbank einige Zeit dauern).

Importieren kann man analog mit mysql:

mysql -u <user> -p -D <datenbank> < dump.sql

02.11.2015 09:50

18 Ranma (Gast)

Für das Exportieren von größeren Datenbanken eignet sich das Konsolen-Tool mysqldump, z.B.:

mysqldump -u <user> -p -D <datenbank> > dump.sql


(<user> und <datenbank> entsprechend ersetzen)

Zwar dauert es unerwartet lange, ein paar Listen in meine Datenbank einzulesen, aber ich versuchte mal eine Sicherungskopie auf diese Weise anzulegen. Ergebnis:

mysqldump: unknown option '-D'

Darum versuchte ich es ohne Optionen, die mysqldump --help nicht auflistet. Das listet schon -u nicht auf. Ergebnis davon:

mysqldump: Got error: 2002: Can't connect to local MySQL server through socket '/var/run/mysql/mysql.sock' (2) when trying to connect

Was kann ich da machen?
Ranma

20.11.2015 05:16

19 Jörg Kruse

Ah OK, mysqldump kennt im Gegensatz zu mysql(-client) keine Option -D - das hatte ich falsch in Erinnerung. In diesem Fall kannst du das -D einfach weglassen:

mysqldump -u <user> -p <datenbank> > dump.sql

Die Option -u sollte mysqldump aber kennen:

· --user=user_name, -u user_name

The MySQL user name to use when connecting to the server.

mysqldump: Got error: 2002: Can't connect to local MySQL server through socket '/var/run/mysql/mysql.sock' (2) when trying to connect

Das ist jedenfalls kein Authentifizierungsfehler. Falls der mysql Client im Gegensatz zu mysqldump funktioniert, befindet sich die socket Direktive in der Konfigurationdatei my.cnf möglicherweise im falschen Abschnitt - siehe den Lösungsvorschlag auf stackexchange:

http://dba.stackexchange.com/questions/46296/mysql-works-mysqldump-doesnt

20.11.2015 14:06 | geändert: 20.11.2015 14:07

20 Ranma (Gast)

Da war eine Datei mysql.sock von 0 Byte Größe und ohne Inhalt, in den anscheinend üblichen Verzeichnissen war keine der gesuchten Dateien, aber in /etc eine my.cnf, über die nichtmal die Größe in Erfahrung zu bringen war und wohl auch nicht funktionierte. Fast hätte ich die Dateien nicht gefunden. Unter lampp/etc ist auch noch eine my.cnf, deren Einstellungen richtig waren und die das kopieren nach /etc empfahl. Also habe ich die dortige my.cnf damit ersetzt. Seitdem funktioniert mysqldump und produzierte eine so große Datei, daß ich die nicht im Editor ansehen konnte, um zu sehen, ob das wie vorgesehen geklappt hat. Zumindest ist sie groß genug, um die Datenbank zu enthalten.
Ranma

25.11.2015 08:20

Beitrag schreiben (als Gast)

Die Antwort wird nach der Überprüfung durch einen Moderator freigeschaltet.





[BBCode-Hilfe]