Insertion Fichier xml dans BDD avec des sous noeuds

Petit nouveau ! | 3 Messages

18 janv. 2011, 11:23

Bonjour,

Je recherche de l'aide concernant une insertion en php d'un fichier xml avec des sous noeuds identique.
Le fichier xml est envoyé automatiquement tous les jours sur un ftp.

Code fichier immo.xml :

Code : Tout sélectionner

<?xml version="1.0" encoding="iso-8859-15" standalone="yes"?> <biens> <bien id="0"> <reference>1234</reference> <code_agence>1</code_agence> <num_mandat>m1</num_mandat> <nom_agence>xxx</nom_agence> <code_postal>00000</code_postal> <ville>XXXX</ville> <type_bien>maison</type_bien> <prix>72000</prix> <images> <image>http://xxx.com/image/1234_1_1_M.jpg</image> <image>http://xxx.com/image/1234_1_2_M.jpg</image> <image>http://xxx.com/image/1234_1_3_M.jpg</image> <image>http://xxx.com/image/1234_1_4_M.jpg</image> <image>http://xxx.com/image/1234_1_5_M.jpg</image> </images> </bien> <bien id="1"> <reference>5678</reference> <code_agence>1</code_agence> <num_mandat>m2</num_mandat> <nom_agence>xxx</nom_agence> <code_postal>00000</code_postal> <ville>XXXX</ville> <type_bien>appartement</type_bien> <prix>52000</prix> <images> <image>http://xxx.com/image/5678_1_1_M.jpg</image> <image>http://xxx.com/image/5678_1_2_M.jpg</image> <image>http://xxx.com/image/5678_1_3_M.jpg</image> </images> </bien> </biens>

J'arrive à insérer tous les champs dans ma base de données sauf les images. C'est que la 1ère image qui est insérée. Mon problème se situe donc sur l'insertion des images.

Code insert.php :
<?php 
function apo($s1) 
{ 
$s1 = trim($s1); // suppr les espaces 
$s1 = trim($s1, "\xA0" ); // suppr les nbsp 
$s1 = stripslashes($s1); // suppr les slashs avant les apostrophes 
$s1 = str_replace("'", "''", $s1); // remplace les guillemets 

// supprime les caractères non imprimables 
$s2 = ""; 
for ($i = 0; $i < strlen($s1); $i++) { 
$c = substr($s1, $i, 1); 
if (ord($c) >= 32) 
$s2 .= $c; 
} 
return($s2); 
} 

// Récupération du fichier 
$recup = simplexml_load_file("http://www.xxx.com/dossier/immo.xml"); 

// On lance la fonction 
frecur($recup); 

/** 
Fonction frecur 
*/ 
function frecur($racine, $niveau = 0) { 
// Pour chaque item 
foreach($racine as $nom=>$texte) { 
// Pour le noeud enfant 
if(trim($texte) == "") { 
for($i=1;$i<=$niveau;$i++) { echo " "; } 
// on affiche le nom 
echo "La balise <strong>".$nom."</strong>"; 
// on récupere les enfants 
$enfants = $texte->children(); 
// on récupere les attributs s'ils sont présents 
$str = ""; 
$attributs = $texte->attributes(); 

if(trim($attributs) != "") { 
$str = "("; 
foreach($attributs as $index=>$contenu) { 
$str .= "[<strong>".$index."</strong>] <em>".$contenu."</em>, "; 
} 
$str = substr($str, 0, -2).")"; // Pour la mise en forme 
} 
echo $str." 
"; 

// comme on a un enfant, on réappelle la fonction (le niveau sert juste à la mise en forme) 
frecur($enfants, $niveau + 0); 

$bien=$texte; 
} else { 
// si on n'a pas d'enfant, on affiche ce qu'il y a dedans 
for($i=1;$i<=$niveau;$i++) { echo " ";} 
echo "La balise <strong>".$nom."</strong> contient <em>".$texte."<br />\n</em> 
"; 
} 
mysql_query("INSERT INTO table SET BienReference='".apo($bien->reference)."' ,BienAgence='".apo($bien->code_agence)."' ,BienMandat='".apo($bien->num_mandat)."' ,AgenceNom='".apo($bien->nom_agence)."' ,BienCodePostal='".apo($bien->code_postal)."' ,BienVille='".apo($bien->ville)."' ,BienType='".apo($bien->type_bien)."' ,BienPrix='".apo($bien->prix)."' ,BienImages1='".apo($elem->images->image)."' ,BienImages2='".apo($elem->images->image)."' ,BienImages3='".apo($enfants->images->image)."' ,BienImages4='".apo($enfants->images->image)."' ,BienImages5='".apo($enfants->images->image)."'") or die("Erreur MySQL : ".mysql_error()); 
} 
} 
?> 

Merci pour votre aide.

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

18 janv. 2011, 13:11

Bonjour,

Dans l'arbre "bien" il y un deuxième niveau d'arborescence nommé "images" qu'il faut aussi parcourir pour la linéarisation des URL d'images d'un bien dans les champs "BienImageX" où X est le n° de série de l'image. C'est ce que tu ne fais pas dans ton script.

Mais j'ai une autre remarque qui concerne la structure de lecture de ton xml : En effet, ton algorithme fait un appel récursif à la fonction de lecture "frecur" comme si la structure-type de ton XML n'est pas connu d'avance ; Or c'est faux, la structure-type du document XML est figée (la preuve est que tu fais référence absolue aux noms des éléments XML dans la chaine SQL correspondant aux champs de la table de la BDD. Ce qui est normal. Donc, puisque la structure de la table de la BDD correspond à celle du XML, l'algorithme doit être vraiment spécifique et du coup peut être simplifié en évitant la récursivité et en traitant l'objet XML extrait du document XML comme un tableau d'objets (éléments, attributs et autres nœuds xml)

Voici une démonstration de simplification en reprenant ton code d'origine:
1. Voici un essai de lecture totale du document XML dans un objet XML exploitable comme un tableau d'objets:
function frecur($racine) {
// Pour chaque item
	foreach($racine as $bien) { 
		echo "<pre>"; print_r($bien); echo "</pre>";
        }
}
Ce programme lit tous les biens via la variable objet $bien. Le print_r() nous permet de voir la structure interne de l'objet $bien, exemple:
SimpleXMLElement Object
(
[@attributes] => Array
(
[id] => 0
)

[reference] => 1234
[code_agence] => 1
[num_mandat] => m1
[nom_agence] => xxx
[code_postal] => 00000
[ville] => XXXX
[type_bien] => maison
[prix] => 72000
[images] => SimpleXMLElement Object
(
[image] => Array
(
[0] => http://xxx.com/image/1234_1_1_M.jpg
[1] => http://xxx.com/image/1234_1_2_M.jpg
[2] => http://xxx.com/image/1234_1_3_M.jpg
[3] => http://xxx.com/image/1234_1_4_M.jpg
[4] => http://xxx.com/image/1234_1_5_M.jpg
)

)

)
Ceci nous permet de voir et comprendre comment sont structurés les champs et le données dans l'objet $bien et par conséquent, nous donne déjà une idée sur la suite de l'algorithme nécessaire pour accéder aux champs xml et les placer convenablement dans la requête SQL.
De ce fait, on peut voir aussi la structure du nœud "images" sous-jacente à l'objet $bien. Ce qui nous permet de dire que l'élément $bien->images->image est un tableau (Array) qu'on doit parcourir pour accéder aux URL des images d'un bien.

D'où l'algorithme suivant:
function frecur($racine) {
// Pour chaque item
	foreach($racine as $bien) { 
		echo "<pre>"; print_r($bien); echo "</pre>";
		## Traitement des url des images du bien en cours
		$champs_SQL_images = array();
		$i = 1;
		foreach($bien->images->image as $url) {
			$champs_SQL_images[] = " BienImages" . $i . "='" . $url . "'"; # champs SQL-URLs contruits un/un dans un tableau
			$i++;
		}
		$champs_SQL_images = implode(',', $champs_SQL_images); # construction des champs SQL séparés par virgule

#### Affichage pour le Test de la requête SQL 
               echo ("INSERT INTO table SET BienReference='".apo($bien->reference)."' , BienAgence='".apo($bien->code_agence)
		."' , BienMandat='".apo($bien->num_mandat)."' , AgenceNom='".apo($bien->nom_agence)
		."' , BienCodePostal='".apo($bien->code_postal)."' , BienVille='".apo($bien->ville)
		."' , BienType='".apo($bien->type_bien)."' , BienPrix='".apo($bien->prix)."', " .$champs_SQL_images);
		echo "<br />";
	}
}
J'espère que j'ai clarifié un peu le sujet :wink:
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Petit nouveau ! | 3 Messages

18 janv. 2011, 13:36

Merci pour ta réponse plus que complète ! Je regarde tout ça dans la soirée et je te tiens au courant. Encore merci ! :D

ViPHP
ViPHP | 5462 Messages

18 janv. 2011, 17:38

c'est hyper compliquer pour pas grand chose quand même t'arrive a t'y retrouver dans ton code ? de plus que y'a pas de récursivité la dedans

un truc comme ca m'a l'air plus sympa :
ca serait encore plus simple avec PDO
ini_set('mysql.trace_mode', true);

$xml = simplexml_load_file('http://www.xxx.com/dossier/immo.xml');

$table = array(
    'reference'   => 'BienReference',
    'code_agence' => 'BienAgence',
    'num_mandat'  => 'BienMandat',
    'nom_agence'  => 'AgenceNom',
    'code_postal' => 'BienCodePostal',
    'ville'       => 'BienVille',
    'type_bien'   => 'BienType',
    'prix'        => 'BienPrix',
    'image1'      => 'BienImages1',
    'image2'      => 'BienImages2',
    'image3'      => 'BienImages3',
    'image4'      => 'BienImages4',
    'image5'      => 'BienImages5',
);

foreach($xml->bien as $bien)
{
    $data = array();
    
    foreach($bien as $key => $value)
    {
        if(array_key_exists($key, $table))
        {
            $data[$table[$key]] = sprintf("'%s'", mysql_real_escape_string($value->__toString()));
        }
    }    
    
    $images = (array) $bien->images;

    foreach($images['image'] as $key => $value)
    {
        $key = 'image' . (++$key);
        
        if(array_key_exists($key, $table))
        {
            $data[$table[$key]] = sprintf("'%s'", mysql_real_escape_string($value));
        }
    }

    print_r($data);
    
    $fields = implode(', ', array_keys($data));
    $values = implode(', ', $data);
    
    $sql = sprintf("INSERT INTO table (%s) VALUES(%s)", $fields, $values);
    echo $sql;
    //mysql_query($sql);
}

Petit nouveau ! | 3 Messages

19 janv. 2011, 16:00

Merci pour vos réponses ! Elle m'ont beaucoup aidé à avancer dans mon problème. Grâce à vous, mon code marche nickel !
Encore merci ! :wink: