XML Datei auslesen und DB Updaten

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • XML Datei auslesen und DB Updaten

    Guten Tag,

    ich lese per PHP Script 2 XML Dateien aus, die daten werden direkt in eine DB geschrieben. Die erste XML datei legt per INSERT INTO alle tabelleneinträge an und in der zweiten XML Datei befinden sich zusätzliche Informationen zu den bereits angelegten daten.

    das auslesen und anlegen der DB mit der ersten XML datei funktioniert super, nur die zweite spinnt. Der code um die zweite XML einzulesen sieht so aus:

    PHP-Code:
          if (!file_exists($import_path_text)) {
            print 
    "Error on Course import" .chr(13).chr(10);
          } else {
            
    $xml2 file_get_contents($import_path_text);
            
    $xml2 preg_replace('/ +<\//''</'$xml2);
            
    $xml2 = new SimpleXMLElement($xml2);

            if (
    is_object($xml2) ) {
              foreach (
    $xml2 as $item2) {
              
                
    $id $item2->course_id;
                
    $kursidstring serialize($id);
                
    $beschreibung $item2->Text;
              

                        
    $eintrag2 "UPDATE hfkplan_table Set beschreibung = '$beschreibung' WHERE kursid = '$kursidstring'";

                        
    $eintragen2 mysql_query($eintrag2);            
                        
    //echo gettype($s); echo '<br />';
                    
    }
                }
            } 
    nun wird das script aber nicht richtig ausgeführt, der bricht nach 60 sekunden ab, mit der meldung, die ausführung dauert zu lange. Auch wenn ich die KursID testweise direkt eingebe und nicht per variable dauert die ausführung des script zu lange, aber immerhin trägt das script dann noch daten ein - dies ist mit variable nicht der fall.

    Die KursID ist bereits aus dem auslesen der ersten XML datei in der Datenbank vorhanden und soll dazu genutzt werden, die Daten aus der zweiten XML Datei (wo die KursID auch nochmal drin steht) dem korrekten Datensatz zuzuweisen.

    Vielleicht hat ja jemand eine Idee, was hier falsch läuft.

    MFG,
    Alex

  • #2
    Hallo,

    was heißt spinnen genau? Was passiert bzw. was passiert nicht? Bist du sicher, dass in der Datenbank serialisierte PHP-Variablen als IDs fungieren? Wenn nicht, was soll dann das serialize? Wenn ja, hör auf mit so nem Scheiß!

    Hast du dir das generierte Statement mal angesehen? Hast du sonstige Debugging-Maßnahmen ergriffen? Warum schützt du deine Datenbank nicht gegen SQL Injections, sondern benutzt Variablen in Strings, was man nicht tun sollte und schon gar nicht im Zusammenhang mit SQL-Statements!

    Gruß,

    Amica
    [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
    Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
    Super, danke!
    [/COLOR]

    Kommentar


    • #3
      Hallo,
      Ist die Datei vielleicht einfach zu groß um sie innerhalbder 60 Sekunden zu durchlaufen ? Auch bietet sich SimpleXml bei größeren Dateien nicht wirklich an, da die gesamte Datei erst einmal vollständig in den Speicher geladen werden muss.

      Versuche die Datei Stückweise abzuarbeiten indem du Immer nur n Knoten pro durchlauf bearbeitest und danach die nächsten n Stück. Hierzu kannst
      Du dir die mal XMLReader Klasse ansehen.

      Gruß Danny
      hostbar - Full Service Internet Agentur

      Kommentar


      • #4
        Ohne nähere Informationen, wie von AmicaNoctis schon moniert, wird man nicht weiterhelfen können.

        Ein Schuss ins Blaue noch: Ist 'hfkplan_table' schon sehr groß? Wenn du dann keinen Index auf 'kursid' hast, könnte die DB ggf. schon recht lange brauchen, den Datensatz zu finden, der das Update bekommen soll und daher könnte dein Script dann in den Timeout rennen.

        Den Hinweis von AmicaNoctis bezüglich serialize solltest du dir auch zu Herzen nehmen. Evtl. hast du da auch das Manual zu PHP: serialize - Manual etwas Missverstanden?
        Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
        Schön - etwas Geschichte kann ja nicht schaden.
        Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

        Kommentar


        • #5
          Hallo,

          vielen dank schonmal für die antworten.

          - Das serialize habe ich reingetan, weil ich die variable $id mit gettype gecheckt habe und er mit als datentyp ein objekt zurückliefert. Mit serialize wollte ich dieses Objekt testweise in einen String umwandeln (google hat mich drauf gebracht) um zu testen, ob die daten dann korrekt eingetragen werden, ist aber auch nicht der fall (in string umwandeln, weil ich nicht weiss, ob in der Datenbankabfrage WHERE kursid = $id mit objekt verglichen werden kann) - mit gettype bekomme ich aber als datentyp jetzt nen string zurück...

          - zum debugging: also ich habe einige sachen getestet, zum beispiel die "beschreibung" einem festen wert und nicht der variable zuzuweisen - das script überschreitet dann auch die 60sekunden, aber dann tauchen in der DB die daten wenigstens auf. Dann habe ich mittels gettype halt noch versucht rauszufinden, ob das irgendwie am datentyp liegt, glaub ich aber nicht.

          - in der DB sind ca 8400 Datensätze vorhanden und die richtigen "beschreibungen" den kursid's zuzuordnen

          - von SQL injections habe ich keine Ahnung, ich bin noch relativ neu auf dem gebiet und das ganze ist auch "nur" ein übungsprojekt ohne irgendwelche Gefahr von außen

          - die XML's haben folgende größe:
          XML1: 5mb (wird vollständig in die DB korrekt eingetragen, der ganze vorgang dauert nur 2-3 sekunden)
          XML2: 3mb (hier stehen nur kursIDs und beschreibungen drin, die kursIDs sollen in der DB gefunden und die beschreibung entsprechend hinzugefügt werden)

          - die XMLReader klasse schaue ich mir auch mal an

          ich weiss gerade nicht, was ich euch noch für infos dazu zukommen lassen kann, dass script ist ja an sich auch nicht wirklich umfangreich ;(

          gruß,
          alex
          Zuletzt geändert von xserio; 03.01.2012, 21:53.

          Kommentar


          • #6
            Zitat von xserio Beitrag anzeigen
            Das serialize habe ich reingetan, weil ich die variable $id mit gettype gecheckt habe und er mit als datentyp ein objekt zurückliefert.
            SimpleXML liefert dir für jeden Knoten ein SimpleXmlElement zurück, welches du aber in einen String umwandeln kannst. Wenn du von diesem String die Zahl 0 abziehst, bekommst du einen Integer. Serialize dagegen macht aus allem eine maschinenlesbare Repräsentation, mit der absolut niemand außer der unserialize-Funktion etwas anfangen können soll.

            Es ist wichtig, dass du dich mit ganz simplem Debugging beschäftigst, also Testausgaben mit var_dump machst, um den Inhalt deiner Variablen vor deren Verwendung zu prüfen. Dann würden dir solche Sachen schon auffallen, bevor sie dir ein Problem bereiten.

            Da ich dir (aufgrund fehlender Grundkenntnisse) immer noch nicht abnehmen kann, dass deine DB vernünftig aufgebaut ist, hätte ich gerne mal die CREATE TABLE-Statements (Export zu SQL, nur Struktur, keine Daten) gesehen.

            Gruß,

            Amica
            [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
            Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
            Super, danke!
            [/COLOR]

            Kommentar


            • #7
              Hallo,

              ich habe nun mal die $id und $beschreibung variablen (das serialize hab ich entfernt) per var_dump (danke für den tip) analysiert, das kam dabei raus und macht für mich einen korrekten eindruck (dir IDs stimmen mit den KursIDs, die in der DB stehen überein) und mehr variablen sind ja auch nicht in der MySQL Update anweisung...

              $id:
              object(SimpleXMLElement)#20 (1) { [0]=> string(15) "328814143326384" } object(SimpleXMLElement)#19 (1) { [0]=> string(15) "328814370138417" } USW. bis scriptabbruch

              $beschreibung:
              object(SimpleXMLElement)#20 (1) { [0]=> string(146) "Grundbegriffe der Medienproduktion, Satzspiegel, Typgrafie, Stilvorlagen, Bildplatzierung und -bearbeitung, ICC-Profilierung. PDF-Export, Drucken " }
              object(SimpleXMLElement)#19 (1) { [0]=> string(54) "Pflichtveranstaltung für alle Studierenden der Klasse" } USW. bis scriptabbruch

              - was mich etwas wundert, ist, dass die zahlen hinter der raute immer zwischen 19 und 24 liegen, also sich auch wiederholen -> ist das normal?

              und hier das create table, alle infos bis auf die beschreibung lese ich aus der ersten XML aus und die werden auch korrekt eingetragen (~8400 datensätze)

              Code:
              mysql_query("CREATE TABLE hfkplan_table(
              						id INT NOT NULL AUTO_INCREMENT, 
              						PRIMARY KEY(id),
              						kursid VARCHAR(20) COLLATE utf8_unicode_ci,
              						datum TEXT COLLATE utf8_unicode_ci,
              						vorname VARCHAR(50) COLLATE utf8_unicode_ci,
              						nachname VARCHAR(50) COLLATE utf8_unicode_ci,
              						kursname TEXT COLLATE utf8_unicode_ci,
              						raum VARCHAR(10) COLLATE utf8_unicode_ci,
              						beginn CHAR(5) COLLATE utf8_unicode_ci,
              						ende CHAR(5) COLLATE utf8_unicode_ci,		
              						beschreibung TEXT COLLATE utf8_unicode_ci,
              						info TEXT COLLATE utf8_unicode_ci)")
              	or die("Erstellen der neuen Tabelle nicht erfolgreich: " . mysql_error());  
              	echo "neue Tabelle erfolgreich erstellt, fange mit befüllen an";
              gruß,
              alex
              Zuletzt geändert von xserio; 04.01.2012, 12:48.

              Kommentar


              • #8
                ich hab gerade festgestellt, dass mein script auch beim einlesen der ersten XML wegen zu langer laufzeit abbricht, und der fehler tritt auf seitdem ich das zweite script versuche einzulesen, ich glaube hier stimmt eher was mit der foreach/if anweisung nicht, hier mal das komplette script:

                PHP-Code:
                    $conn = @mysql_connect($dbhost,$dbuser,$dbpasswort) or die("Abbruch: Verbindung zu '$dbhost'"." konnte nicht hergestellt werden.");
                    @
                mysql_select_db($dbdatabase) or die("Abbruch: Datenbank '$dbdatabase' konnte nicht"." selektiert werden.<br><br>MySQL sagt: ".mysql_error());
                    echo 
                "Verbindung zur Datenbank erfolgreich<br />";
                    
                    
                // Alte hfkplan_table löschen
                    
                    
                $sql "DROP TABLE $dbtable";
                    
                $retval mysql_query$sql$conn );
                            if(! 
                $retval )
                                { die(
                "Datenbank konnte nicht gelöscht werden: " mysql_error()); }
                        echo 
                "Das löschen der alten Datenbank-Tabelle war erfolgreich <br/>";
                    
                    
                    
                // Neue hfkplan_table erstellen
                    
                    
                mysql_query("CREATE TABLE hfkplan_table(
                                        id INT NOT NULL AUTO_INCREMENT, 
                                        PRIMARY KEY(id),
                                        kursid VARCHAR(20) COLLATE utf8_unicode_ci,
                                        datum TEXT COLLATE utf8_unicode_ci,
                                        vorname VARCHAR(50) COLLATE utf8_unicode_ci,
                                        nachname VARCHAR(50) COLLATE utf8_unicode_ci,
                                        kursname TEXT COLLATE utf8_unicode_ci,
                                        raum VARCHAR(10) COLLATE utf8_unicode_ci,
                                        beginn CHAR(5) COLLATE utf8_unicode_ci,
                                        ende CHAR(5) COLLATE utf8_unicode_ci,        
                                        beschreibung TEXT,
                                        info TEXT)"
                )
                    or die(
                "Erstellen der neuen Tabelle nicht erfolgreich: " mysql_error());  
                    echo 
                "neue Tabelle erfolgreich erstellt, fange mit befüllen an";
                    
                    
                // Neue hfkplan_table mit Daten aus den XML Dateien befüllen

                  
                $import_path 'data/' 'veranstaltung.xml';
                  
                $import_path_text 'data/''veranstaltung_text.xml';
                  
                  if (!
                file_exists($import_path)) {
                    print 
                "Error on Course import" .chr(13).chr(10);
                  } else {
                    
                $xml file_get_contents($import_path);
                    
                $xml preg_replace('/ +<\//''</'$xml);
                    
                $xml = new SimpleXMLElement($xml);
                    
                    if (
                is_object($xml) ) {
                      foreach (
                $xml as $item) {
                      
                      
                $kursname $item->course_name;
                      
                $kursid $item->course_id;
                      
                $vorname $item->first_name;
                      
                $nachname $item->last_name;
                      
                $beginn $item->time_from;
                      
                $ende $item->time_to;
                      
                $raum $item->add_rooms;
                      
                $datum $item->timetable_date;
                      
                      
                // Datum format aendern (von zb 2011-11-2700:00:00 auf 27.11.2011)
                      
                        
                $datum substr($datum,0,10);  // 00:00:00 entfernen
                        
                $datumtag substr($datum,8,2);  // datum umschreiben -> evtl zwecks besserer Sortiermöglichkeiten wieder amerikanisches Format!
                        
                $datummonat substr($datum,5,2);
                        
                $datumjahr substr($datum,0,4);
                        
                $datum $datumtag.".".$datummonat.".".$datumjahr;
                        
                      

                                
                $eintrag "INSERT INTO hfkplan_table
                                            (datum, kursid, vorname, nachname, kursname, raum, beginn, ende)

                                            VALUES
                                            ('
                $datum' , '$kursid' , '$vorname' , '$nachname' , '$kursname' , '$raum' , '$beginn' , '$ende')";
                                
                var_dump($kursname); echo '<br />';    
                                
                $eintragen mysql_query($eintrag);
                                
                        }
                    }
                }
                        
                      
                // Kurs Beschreibungen aus veranstaltungen_text.xml eintragen
                        
                      
                if (!file_exists($import_path_text)) {
                        print 
                "Error on Course import" .chr(13).chr(10);
                      } else {
                        
                $xml2 file_get_contents($import_path_text);
                        
                $xml2 preg_replace('/ +<\//''</'$xml2);
                        
                $xml2 = new SimpleXMLElement($xml2);

                        if (
                is_object($xml2) ) {
                          foreach (
                $xml2 as $item2) {
                          
                            
                $id $item2->course_id;
                            
                $beschreibung $item2->Text;
                          

                                    
                $eintrag2 "UPDATE hfkplan_table Set beschreibung = '$beschreibung' WHERE kursid = '$id'";

                                    
                $eintragen2 mysql_query($eintrag2);
                                                    
                                    
                //echo gettype($s); echo '<br />';
                                
                }
                            }
                        }


                    
                // DB Verbindung schliessen
                    
                    
                mysql_close($conn); 
                ich werd jetzt nochmal ein bisschen im trüben fischen und hoffen das ich die richtige lösung irgendwie errate =D

                gruß

                Kommentar


                • #9
                  Zitat von xserio Beitrag anzeigen
                  ich werd jetzt nochmal ein bisschen im trüben fischen und hoffen das ich die richtige lösung irgendwie errate =D
                  Raten ist immer gut

                  Du liest also im ersten Schritt immer die 8400 Datensätze aus der XML ein?
                  XML parsen ist immer etwas rechenintensiv, weshalb ich mir je nach System schon vorstellen kann, dass 60 Sekunden max_execution_time schon nicht ausreichen um überhaupt alles einzulesen.

                  Was dann den zweiten Schritt angeht: Hier hab ich mit meinem Schuss ins Blaue wohl voll in die Mitte getroffen. Es fehlt ein Index auf 'kursid' - mach es mySql doch mal etwas leichter den Datensatz zu finden, den es updaten soll: MySQL :: MySQL 5.1 Referenzhandbuch :: 7.4.3 Spaltenindizes
                  Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
                  Schön - etwas Geschichte kann ja nicht schaden.
                  Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

                  Kommentar


                  • #10
                    Zitat von Quetschi Beitrag anzeigen
                    Raten ist immer gut

                    Du liest also im ersten Schritt immer die 8400 Datensätze aus der XML ein?
                    XML parsen ist immer etwas rechenintensiv, weshalb ich mir je nach System schon vorstellen kann, dass 60 Sekunden max_execution_time schon nicht ausreichen um überhaupt alles einzulesen.

                    Was dann den zweiten Schritt angeht: Hier hab ich mit meinem Schuss ins Blaue wohl voll in die Mitte getroffen. Es fehlt ein Index auf 'kursid' - mach es mySql doch mal etwas leichter den Datensatz zu finden, den es updaten soll: MySQL :: MySQL 5.1 Referenzhandbuch :: 7.4.3 Spaltenindizes
                    hallo,

                    ich habe die max_execution_time des scripts mal auf 5 minuten hochgeschraubt und siehe da, es funktioniert alles. Hat mich gewundert, dass die 8400 Datensätze per INSERT innnerhalb von 2-3 Sekunden verarbeitet sind, aber per UPDATE die max_execution_time von 60 sekunden nicht ausreicht o_O. Ich werde mir das mit dem spaltenindex jetzt noch einmal genauer anschauen um die laufzeit ggf. zu verkürzen, aber ihr habt mir alle schon sehr geholfen

                    gruß

                    Kommentar


                    • #11
                      Wenn die kursid nummerisch ist, sollte sie auch als int (oder bigint) erstellt werden und sie sollte unbedingt einen Schlüssel bekommen, entweder einen unique key wenn sie eindeutig ist oder einen einfachen index. Was sind beginn und ende? Wenn es Uhrzeiten sind, nimm eine TIME-Spalte. Überhaupt solltest du immer den passendsten Spaltentyp nehmen, weil das bei späteren Abfragen i. d. R. bessere Performance bringt als String-Vergleiche auf [var]char-Spalten.

                      Edit: Ups, ich war zu lange weg, das wichtigste ist ja schon beantwortet. Zwinker@Quetschi
                      Zuletzt geändert von AmicaNoctis; 04.01.2012, 15:26.
                      [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
                      Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
                      Super, danke!
                      [/COLOR]

                      Kommentar


                      • #12
                        @AmicaNoctis
                        Dafür war ich nicht so ausführlich wie du

                        @xserio
                        ... und wenn das Feld 'datum' das ist, was es zu sein scheint, dann gibts auch dafür einen weitaus besseren Datentyp als TEXT

                        Hier wär auch nochmal etwas Lektüre für dich, die du scheinbar dringend nötig hast:
                        MySQL :: MySQL 5.1 Referenzhandbuch :: 11 Datentypen
                        Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
                        Schön - etwas Geschichte kann ja nicht schaden.
                        Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

                        Kommentar


                        • #13
                          ja mit den datentypen habe ich mich ehrlich gesagt noch nicht so sehr befasst, da ich dachte, meine datenmenge ist eh so gering, das der quasi "alles frisst"
                          - ich guck mir das nochmal genauer an

                          gruß

                          Kommentar

                          Lädt...
                          X