Parser en php un fichier xml

WRInaute passionné
Salut à tous,

J'ai un fichier xml de ce type :
Code:
<root time="200611123100277">
<item id="92605361" str="34138" pr="600.95" cty="USA" st="New York"/>
<item id="92605362" str="35531" pr="630.05" cty="USA" st="Los Angeles"/>
<item id="92605363" str="45640" pr="2230.25" cty="France" st="Paris"/>
<item id="92605364" str="52659" pr="3230.55" cty="France" st="Lyon"/>
</root>
Comment faut-il faire pour parser en php ce fichier et récupérer les valeurs qui sont dans : id, str, pr, ctv et st ?

Merci d'avance pour votre aide.
 
WRInaute accro
simplexml_load_file

PHP:
<?php

$string = <<<EOT
<root time="200611123100277">
<item id="92605361" str="34138" pr="600.95" cty="USA" st="New York"/>
<item id="92605362" str="35531" pr="630.05" cty="USA" st="Los Angeles"/>
<item id="92605363" str="45640" pr="2230.25" cty="France" st="Paris"/>
<item id="92605364" str="52659" pr="3230.55" cty="France" st="Lyon"/>
</root>
EOT;

$xml = simplexml_load_string($string);
foreach ($xml->item as $item) {
    foreach ($item->attributes() as $k => $v) {
        echo "$k = $v" . PHP_EOL;
    }
}
 
Dernière édition:
WRInaute passionné
Merci spout, ton code marche parfaitement bien.

Par contre, comment je dois faire pour mon fichier xml qui est dans la variable $string ci-dessous ?

$string = "".$_SERVER['DOCUMENT_ROOT']."/mon_fichier.xml";

Si je remplace ta variable $string par la mienne ci-dessus, ça ne marche plus :(
 
WRInaute accro
La réponse est à la première ligne.
Tu remplaces :
PHP:
$xml = simplexml_load_string($string);
par :
PHP:
$xml = simplexml_load_file($_SERVER['DOCUMENT_ROOT'] . "/mon_fichier.xml");
 
WRInaute passionné
Merci spout, effectivement ça marche mieux comme cela ;)

Je voudrais maintenant ajouter les données contenues dans la variable $v dans une table MySQL, mais il faudrait qu'à chaque "id" on ajoute dans les bonnes colonnes de ma table les variables (id, str, pr, ctv, st) qui correspondent à cet "id" et qu'au prochain "id" on les inserts dans une autre ligne de ma table.

L'autre souci, c'est que le nombre d'attributs contenus dans <item> peut-être différent du nombre de colonnes de ma table MySql, donc il faudrait vérifier à chaque insertion que la valeur contenue dans la variable $k corresponde bien au nom de la colonne de ma table MySQL avant l'insertion des données.

Comment faire tout cela ?
 
WRInaute passionné
Mon fichier xml étant trop volumineux (300 Mo), je pense que la meilleure solution est de créer un fichier csv à partir de mon fichier xml et d'importer les données dans ma table Mysql via "LOAD DATA LOCAL INFILE".

J'ai donc crée une fonction php "createCsv" qui crée ce fichier csv. Cela marche bien mais il manque dans ce fichier csv un délimiteur de ligne (un retour à la ligne à la fin de chaque ligne).

Voici le résultat obtenu actuellement :
Code:
92605361,34138,600.95,USA,New York,92605362,35531,630.05,USA,Los Angeles,92605363,45640,2230.25,France,Paris,92605364,52659,3230.55,France,Lyon

J'aimerai obtenir ceci :
Code:
92605361,34138,600.95,USA,New York
92605362,35531,630.05,USA,Los Angeles
92605363,45640,2230.25,France,Paris
92605364,52659,3230.55,France,Lyon

Voici mon code php :
Code:
function createCsv($xml,$f)
{
    foreach ($xml->item as $item)
    {
        foreach ($item->attributes() as $k => $v){
            $put_arr = array($v,$item);
            fputcsv($f, $put_arr ,',' ,'"');
        }
    createCsv($item, $f);
    }
}

$filexml = file_get_contents("".$_SERVER['DOCUMENT_ROOT']."/scripts/test.xml");
$xml = simplexml_load_string($filexml);
$f = fopen("".$_SERVER['DOCUMENT_ROOT']."/scripts/test.csv", "a+");
createCsv($xml, $f);
fclose($f);

Que dois-je modifier dans ma fonction "createCsv" pour ajouter un retour à la ligne à la fin de chaque ligne ?
 
WRInaute passionné
Merci spout.

Plutôt que de créer un fichier csv à partir d'un fichier xml, je viens de voir qu'il est possible d'importer des données directement à partir d'un fichier xml avec la commande mysql "LOAD XML LOCAL INFILE", j'ai donc essayé et ça ne marche qu'à moitié :(

Mon fichier test xml comporte 262 lignes, lorsque je lance la commande MySQL "LOAD XML LOCAL INFILE 'C:/wamp/www/mon-site/test.xml' INTO TABLE `ma_table` ROWS IDENTIFIED BY '<item>'", il y a bien 262 lignes qui sont importées dans ma table MySQL mais toutes les valeurs des attributs de mon fichier xml sont nulles.

Lorsque je rentre manuellement la commande "LOAD XML LOCAL INFILE 'C:/wamp/www/mon-site/test.xml' INTO TABLE `ma_table` ROWS IDENTIFIED BY '<item>'" dans l'onglet "SQL" de PhpMyAdmin j'ai une croix rouge sur la gauche qui m'indique lorsque je pose ma souris dessus : Type d'énoncé non reconnu (près de LOAD)



J'ai la version 5.7 de MySQL. Peut-on utiliser "LOAD XML LOCAL INFILE" avec cette version de MySQL ?
 
WRInaute passionné
"LOAD XML LOCAL INFILE" ne fonctionne pas correctement en local (j'ai pas essayé sur mon serveur de production mais bon...) :(

J'ai essayé de créer un fichier csv à partir du fichier xml mais mon fichier xml étant trop gros (380 Mo), le délai est trop important pour réaliser cette tache, ça m'a fait planté l'ordi :(

Je pense donc que la solution est de fragmenter l'import des données dans ma table MySQL en limitant le nombre de lignes importées à 50000 par exemple.

Donc il faudrait créer une boucle qui importe dans ma table MySQL (via "LOAD LOCAL INFILE") à partir de mon fichier csv les lignes de 0 à 50000 et une deuxième boucle qui importe les lignes de 50001 à 100000 et plus une autre de 100001 à 150000, etc.. jusqu'à la fin du nombre de lignes de mon fichier csv, comment faire cette boucle ?
 
WRInaute accro
Oui mais tu fais ça via PhpMyAdmin aussi, ça bloque le serveur HTTP le temps du traitement, pas génial.
Tu as testé en CLI ?
 
WRInaute passionné
Merci spout.

J'ai trouvé une solution pour convertir mes données en csv et importer en une seule fois toutes les données dans ma table MySQL (via "LOAD LOCAL INFILE"). La rapidité de LOAD LOCAL INFILE est incomparable lorsqu'on souhaite importer une grosse quantité de données.

Merci pour ton aide spout.
 
Discussions similaires
Haut