S'il rajoute des propriétés dans son XML, c'est pas un soucis : les premières indications que je te donnais concernant la gestion des propriété permet de gérer ça facilement.
Ainsi, pour les propriétés obligatoires, tu sais desquelles il s'agit : quand tu les rencontres, tu connais la valeur du champ pour insérer le produit dans la table.
Pour les propriétés inconnues, il va falloir :
- vérifier si la propriété existe ou non dans la table (récupérer son ID si oui, l'insérer et récupérer son ID si non)
- insérer dans la table de jointure attribut-produit l'id du produit, l'id de la propriété (= de l'attribut) et la valeur (le nom du fichier photo par exemple)
C'est tout.
Pour revenir à la création du XML à partir des rubriques... Ta table n'est pas correctement construite, parce qu'elle ne prend pas en compte une contrainte pourtant manifeste dans le fichier XML : une rubrique peut avoir plusieurs parents. Telle que ta table est faite, une rubrique ne peut avoir qu'une seule rubrique parent, à moins de dupliquer son nom dans la table, ce qui conduirait à une incohérence de la base de données : tu aurais plusieurs données portant le même nom (car la même rubrique) mais avec des ID différents.
En analyse, la relation rubrique-rubrique_parent est une relation n,n : une rubrique peut avoir plusieurs enfants, un enfant peut avoir plusieurs parents.
Conceptuellement, l'élément Rubrique est relié à lui-même. Physiquement, une table supplémentaire matérialise cette relation. Ca donne :
RUBRIQUE
- id_rubrique
- nom_rubrique
RUBRIQUE_REL
- id_rubrique
- id_rubrique_parent
Dans cette table RUBRIQUE_REL, l'ID d'une rubrique peut se retrouver plusieurs fois dans chacune des deux colonnes, mais jamais les deux sur la même ligne (une rubrique ne pouvant être sa propre fille !)
Pour récupérer la liste des rubriques et de leurs parents, c'est un peu moins évident, mais c'est quand même tout à fait faisable (avec un peu d'algo, on s'en sort).
Il faut faire une requête qui porte sur les deux tables. On va récupérer dans cette requête plusieurs fois l'id de la rubrique courante : c'est normal si elle a plusieurs parents. Essaie cette requête, tu vas être surpris ;)
SELECT r.*, rr.id_rubrique_parent AS id_parent FROM rubrique r LEFT JOIN rubrique_rel rr ON r.id_rubrique=rr.id_rubrique ORDER BY r.id_rubrique
J'ai créé les tables en local, avec les données que tu m'as données. La requête me retourne, avec mes deux tables différentes de la tienne, exactement les mêmes résultats que si j'avais fait un select * sur ta table. La différence : je peux avoir plusieurs parents pour une même rubrique, et une rubrique peut avoir plusieurs enfants.
Voici le code SQL pour construire les tables comme je les ai faites chez moi :
CREATE TABLE IF NOT EXISTS `rubrique` (
`id_rubrique` int(10) unsigned NOT NULL AUTO_INCREMENT,
`nom_rubrique` varchar(255) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id_rubrique`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=7 ;
INSERT INTO `rubrique` (`id_rubrique`, `nom_rubrique`) VALUES (1, 'Les bécanes'), (2, 'Les accessoires'), (3, 'Les sportives'),
(4, 'Les roadsters'), (5, 'Roadsters anglais'), (6, 'Sportives japonaises');
CREATE TABLE IF NOT EXISTS `rubrique_rel` (
`id_rubrique` int(10) unsigned NOT NULL,
`id_rubrique_parent` int(10) unsigned NOT NULL,
PRIMARY KEY (`id_rubrique`,`id_rubrique_parent`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `rubrique_rel` (`id_rubrique`, `id_rubrique_parent`) VALUES (3, 1), (4, 1), (5, 4), (6, 3);
J'ai rajouté une rubrique "Décorations pour sportives" (oui, c'est farfelu, on s'en fout :) ). Dans la table de relation, je lui ai assigné comme parents les rubriques 2 et 6 (accessoires et sportives).
Quand je réexécute la requête SELECT de tout à l'heure, j'ai dans mon résultat, deux fois la rubrique "Décorations pour sportives", avec comme id_parent les 2 et 6. Normal.
Avant de parcourir le résultat de la requête, il faut définir une variable "temporaire" dans laquelle tu vas stocker l'ID de la rubrique en cours et l'initialiser à 0 (zéro) : les ID auto-incrémentiels commencent à 1, il faut mettre une valeur qui ne PEUT PAS exister dans la base, à cause de ce qui suit. Tu dois aussi garder une trace des rubriques
Au début de la boucle qui récupère la ligne suivante, tu compares la valeur de l'id de la rubrique et celui stocké dans la variable temporaire. S'il est différent (ce qui est forcément le cas à la première itération puisqu'il vaut 0), alors on a une nouvelle rubrique : on peut la décrire dans le fichier XML et inscrire le nom de la rubrique parent.
Si l'id dans la variable temporaire et l'id de la rubrique sont identiques, alors il s'agit toujours de la même rubrique, qui a une autre rubrique parent.
Pour chaque rubrique (donc quand la variable temp et l'id de la rubrique courante sont différents) on stocke dans un tableau l'id et le nom de la rubrique, ça permet de récupérer le nom plus tard, notamment quand on fait référence à une rubrique parent (qui doit théoriquement avoir déjà été lue dans le résultat de la requête). Le tableau des rubriques doit être indexé numériquement, avec comme index l'id des rubriques ; schématiquement : $tableau_rubriques[$id_rubrique] = $nom_rubrique;
Donc quand les deux id sont identiques, on a une nouvelle rubrique parent pour la rubrique en cours : on connait son nom grâce au tableau dans lequel on garde la trace des rubriques.
Donc quand on passe à une nouvelle rubrique, si l'id précédent est différent de 0 (si ce n'est pas la première de la liste) on ferme les balises de la rubrique précédente dans le XML et on ouvre celle de la nouvelle.
A la fin (après la boucle), on ferme simplement la rubrique en cours dans le XML.
J'ai essayé de faire le plus clair possible, j'espère que ça l'est donc...
C'est pas la première fois que j'explique ça sur phcps, je crois que je vais devoir faire un article sur mon blog pour expliquer ça de manière générale ^^ Et c'est pas la première fois que je dis que je vais faire un article sur mon blog à propos d'un sujet que je traite plusieurs fois... :/ Arf.
--
Neige
Souvent la réponse à votre question se trouve dans la doc. Commencez par là ;)