XML -> MySQL Import von vorne

Spelmann

Erfahrenes Mitglied
Leider hat alles was ich bis jetzt lokal erfolgreich getestet habe auf dem Server in keiner Weise funktioniert. Ich habe an so vielen Stellen Fehlermeldungen, dass ich mich entschlossen habe von vorn anzufangen und gleich auf dem Server zu entwickeln. Ich würde mich über Unterstützer freuen, die mich nach ihren Möglichkeiten auch bis zur Lösung des Problems begleiten.

Mein erstes Problem:
PHP:
$file = './xml_sources/WWW-one.XML';
$xml = simplexml_load_file(rawurlencode($file));


try {
$test = new SimpleXMLElement($xml);
} catch (Exception $e) {
print "Fehlerhaftes XML?\n";
}
ergibt die Fehlermeldungen:
Code:
Warning: SimpleXMLElement::__construct(): Entity: line 4: parser error : Start tag expected, '<' not found in...
Warning: SimpleXMLElement::__construct(): ^ in...

Die XML enthält nur einen Datensatz aus einer Hand voll Knoten. Alle Knoten werden, schaut man sich den Inhalt an, korrekt geöffnet und geschlossen.
Was meint dann: Start tag expected, '<' not found ?
 
Zuletzt bearbeitet:
1) Warning <> Fehler.

2) Du mischst Zeug durcheinander. Besser gesagt machst du doppelt gemoppelt
Rückgabewert von simplexml_load_file(): ist ein Objekt vom Typ SimpleXMLElement.
Paramter zu SimpleXMLElement::__construct() ist ein String.

Also, entweder simplexml_load_file() oder new SimpleXMLElement(). Aber nicht beides.
Es lohnt sich die PHP-Hilfe zur hand zu nehmen und zu schauen, was die Argumente und Rückgabewerte sind.

PHP:
$test = simplexml_load_file('./xml_sources/WWW-one.XML');

// oder
$xml = file_get_contents('./xml_sources/WWW-one.XML');
$test = new SimpleXMLElement($xml);

//oder direkt das File
$test = new SimpleXMLElement('./xml_sources/WWW-one.XML', NULL, TRUE);
 
Ich habe es mit allen drei Methoden versucht. Ich habe in den letzten 6 Tagen auch einiges dazu gelesen (vieles nicht verstanden)

Alle drei von Dir genannten Methoden enden leider in einer Fehlermeldung wenn ich mein prepared Statement ausführen möchte:
PHP:
$nums = '';
$xml = simplexml_load_file('./xml_sources/WWW-one.XML');


foreach ($xml->HAUPTKATEGORIE->KATEGORIE->ARTIKEL as $elems) {

    $i_test = 0;
    $lfsn = (string)$elems->LFSN;
    $lfkurzbez = (string)$elems->LFKURZBEZ;
    $intartnr = (int)$elems->INTARTNR;
    $setInsert = "'".$intartnr."','".$lfsn."','".$lfkurzbez."'";
    $nums .= '('.$setInsert.'),';

}
$numsFinal = substr($nums, 0, -1); //Das letzte überflüssige Komma am Ende des Strings wird entfernt


//Zusammensetzen der SQL Abfrage und Ausführung
$sqlInsert = 'INSERT INTO `wws_artikel` intartnr, lfsn, lfkurzbez VALUES '.$numsFinal.' ON DUPLICATE KEY UPDATE lfsn=VALUES(lfsn), lfkurzbez=VALUES(lfkurzbez)';
var_dump($sqlInsert); //bis hier noch alles wie es soll
$insert = $db_link->prepare($sqlInsert);
$insert->execute();
$insert->close();
Fehlermeldung bei $insert->execute:
Code:
Fatal error: Call to a member function execute() on boolean
 
Eine Zusammenfassung des Problems:
Oben beschriebener Code funktioniert (nach Korrektur der Klammer) im Prinzip.
Allerdings nur bei manchen XML-Files.

Die XML-Files die nicht funktionieren, habe ich mal in den Firefox geladen. Der interpretiert sie aber soweit als wohlgeformt. Das Gleiche bei einer Prüfung mit dem Dienst Validome

Um zu prüfen ob die oben beschriebene Methode überhaupt bei großen Strings für $numsFinal funktioniert, habe ich via Schleife mal einen Testdatensatz von 20000 Einträgen generiert. Das INSERT Statement hat das ohne zu murren verarbeitet.

Hat jemand eine Idee woran es noch liegen könnte dass bestimmte XML nicht verarbeitet werden können, oder wie ich da noch eine aussagekräftigere Fehlermeldung bekommen kann?
Vielen Dank!
 
Zuletzt bearbeitet:
Wozu ein prepared Statement? Das ist ein normaler SQL.
Ich würde aber wirklich Eintrag um Eintrag mit einem richtigen Prepared Statement abarbeiten.

PHP:
$xml = simplexml_load_file('./xml_sources/WWW-one.XML');

$sqlInsert = 'INSERT INTO `wws_artikel` intartnr, lfsn, lfkurzbez VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE lfsn=VALUES(lfsn), lfkurzbez=VALUES(lfkurzbez)';
$stmt = $db_link->prepare($sqlInsert);

foreach ($xml->HAUPTKATEGORIE->KATEGORIE->ARTIKEL as $elems) {
    $stmt->bind_param('iss', $elems->LFSN, $elems->LFKURZBEZ, $elems->INTARTNR);
    $stmt->execute();
}
$stmt->close();

Irgendwie kommts mir vor, als habe ich die Antwort in den letzten Tageb bereits irgendwo geschrieben...

Nachtrag:
Beim ON DUPLICATE KEY setzt du alles auf die alten Werte. Ist das Extra?
 
Vielen Dank für deine Hilfe!
Irgendwie kommts mir vor, als habe ich die Antwort in den letzten Tageb bereits irgendwo geschrieben
Ich habe ein paar Behauptungen von mir gelöscht, die einer Prüfung unter realen Bedingungen auf dem Server nicht standhielten, um andere Einsteiger in die Thematik nicht in die Irre zu führen. Sorry wenn ich da versehentlich was von Dir entfernt habe! :oops:

Ich würde aber wirklich Eintrag um Eintrag mit einem richtigen Prepared Statement abarbeiten.
Ich habe, als ich mich in das Thema eingelesen habe, viele Hinweise darauf gefunden, dass es nicht performant sei, das zeilenweise zu machen. Deswegen hatte ich nach einer anderen Lösung gesucht, aber die führten ja alle in eine Sackgasse.

Dein Vorschlag erzeugt nun soweit leider einen anderen Fehler:
Code:
Fatal error: Call to a member function bind_param() on boolean in...
Egal ob ich es wie von Dir vorgeschlagen probiere, (Reihenfolge Integer|String|String korrigiert)
PHP:
foreach ($xml->HAUPTKATEGORIE->KATEGORIE->ARTIKEL as $elems) {
    $stmt->bind_param('iss', $elems->INTARTNR, $elems->LFSN, $elems->LFKURZBEZ);
    $stmt->execute();
}
$stmt->close();
oder so
PHP:
foreach ($xml->HAUPTKATEGORIE->KATEGORIE->ARTIKEL as $elems) {
    $intartnr = (int)$elems->INTARTNR;
    $lfsn = (string)$elems->LFSN;
    $lfkurzbez = (string)$elems->LFKURZBEZ;
    $stmt->bind_param('iss', $intartnr, $lfsn, $lfkurzbez);
    $stmt->execute();
}
$stmt->close();
Der Fehler bleibt der Gleiche.
Hast Du vielleicht noch eine Idee?
 
Zuletzt bearbeitet:
Der prepare ist aufs Dach gefallen:
mysqli_prepare() returns a statement object or FALSE if an error occurred.
Lass dir mal den Fehler ausgeben
PHP:
$xml = simplexml_load_file('./xml_sources/WWW-one.XML');
$sqlInsert = 'INSERT INTO `wws_artikel` intartnr, lfsn, lfkurzbez VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE lfsn=VALUES(lfsn), lfkurzbez=VALUES(lfkurzbez)';

if($stmt = $db_link->prepare($sqlInsert)) {
  foreach ($xml->HAUPTKATEGORIE->KATEGORIE->ARTIKEL as $elems) {
  $stmt->bind_param('iss', $elems->LFSN, $elems->LFKURZBEZ, $elems->INTARTNR);
  $stmt->execute();
  }
  $stmt->close();
}else{
  printf("Errormessage: %s\n", $db_link->error);
}
 
Zurück