Précédent   Forum des professionnels en informatique > PHP > Bibliothèques et frameworks > XML > DOM
DOM Forum d'entraide pour l'extension DOM permettant de manipuler des documents XML en PHP 5 (approche DOM). Avant de poster -> tutoriels DOM
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 11/02/2008, 11h01   #1
Membre à l'essai
 
Inscription : novembre 2007
Messages : 88
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : novembre 2007
Messages : 88
Points : 23
Points : 23
Par défaut [DOM] Ajouter un noeud dans un XML existant

Bonjour tout le monde

Pour mes cours je doit développer une application php, permettant d'ajouter/modifier/supprimer des noeud XML depuis un fichier existant, j'arrive à lire un fichier XML sans problème avec SimpleXML, mon problème ce situe lors de l'ajout, j'ai lu qu'avec SimpleXML il était tout simplement impossible d'ajouter un noeud, mon problème est que je n'y arrive pas avec l'API DOM snif

Voici le fichier XML ( très basique )
Code :
1
2
3
4
5
6
 
<repertoire>
  <personne id="1">
    <nom>un nom</nom>
  </personne>
</repertoire>
j'ai donc une page contenant un simple input texte pour ajouter un nom, mais impossible de modifier le fichier XML existant en ajoutant un noeud <personne>, voici ce que je fait en PHP
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
$dom = new DomDocument();
$dom->load('test.xml');
if($dom->validate()){
  echo "document valide<br />";
  // on crée le nouveau noeud
  $newPersonne = $dom->createElement("personne");
  // on ajoute l'attribut id à <personne>
  $newPersonne->setAttribute("id", "2");
  // on crée le noeud textuel
  $nomPersonne = $dom->createTextNode($_POST['nom']);
 
  $newPersonne->appendChild($nomPersonne);
 
  $dom->save('test.xml');
Je doit être complètement à coter de la plaque car rien ne ce produit, le fichier n'est pas modifier et aucun message d'erreur ( meme avec le report d'erreur php sur E_ALL).
quelqu'un pourrait-il m'expliquer comment je peux enregistré le noeud <personne> contenant l'élément <nom> à la suite de mon fichier XML

d'avance merci de votre aide, je débute avec XML et PHP et vous prie de m'excuser si ce genre de message à déjà été poster
splifferwolf est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/02/2008, 11h28   #2
Membre émérite
 
Avatar de julien.63
 
Inscription : décembre 2005
Messages : 1 322
Détails du profil
Informations forums :
Inscription : décembre 2005
Messages : 1 322
Points : 981
Points : 981
Envoyer un message via MSN à julien.63
salut
essaye ça, j'ai rajoute " $dom->appendChild($newPersonne);" avant de sauver.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$dom = new DomDocument();
$dom->load('test.xml');
if($dom->validate()){
  echo "document valide<br />";
  // on crée le nouveau noeud
  $newPersonne = $dom->createElement("personne");
  // on ajoute l'attribut id à <personne>
  $newPersonne->setAttribute("id", "2");
  // on crée le noeud textuel
  $nomPersonne = $dom->createTextNode($_POST['nom']);
 
  $newPersonne->appendChild($nomPersonne);
 
  $dom->appendChild($newPersonne);
 
  $dom->save('test.xml');
julien.63 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/02/2008, 11h33   #3
En attente de confirmation mail
 
Inscription : juin 2002
Messages : 6 164
Détails du profil
Informations forums :
Inscription : juin 2002
Messages : 6 164
Points : 6 404
Points : 6 404
Pour SimpleXML c'est possible :
Code :
1
2
3
4
5
$sxml = simplexml_load_file('test.xml');
$personne = $sxml->addChild('personne');
$personne->addAttribute('id', '2');
$nom = $personne->addChild('nom', /*utf8_encode*/($_POST['nom']));
$sxml->asXML('test.xml');
Avec DOM :
Code :
1
2
3
4
5
6
7
8
$dom = new DomDocument();
$dom->load('test.xml');
$personne = $dom->createElement('personne');
$personne->setAttribute('id', '2');
$nom = $dom->createElement('nom', /*utf8_encode*/($_POST['nom']));
$personne->appendChild($nom);
$dom->documentElement->appendChild($personne);
$dom->save('test.xml');
Il y a avait quelques petites erreurs : vous ne créiez pas l'élément nom et l'élément référent lors d'un ajout (méthode appendChild) est son père.

(non testé)
julp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/02/2008, 11h41   #4
Membre à l'essai
 
Inscription : novembre 2007
Messages : 88
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : novembre 2007
Messages : 88
Points : 23
Points : 23
merci à vous deux pour vos réponse, j'ai vue et compris ou était mes erreurs grâce à vous et ca devient de suite plus clair, voir même plus logique, celà fonctionne parfaitement maintenant

par contre je ne savais pas que c'était fesable avec SimpleXML on m'a toujours dit que c'était impossible, pourtant ca fonctionne bien aussi.

mille merci à vous
splifferwolf est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/02/2008, 11h47   #5
Membre à l'essai
 
Inscription : novembre 2007
Messages : 88
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : novembre 2007
Messages : 88
Points : 23
Points : 23
temps que je suis dans l'élant

est-il possible de modifier et supprimer un noeud avec SimpleXML ?
puis-je modifier une personne par apport à l'attribut id de personne ?

donc j'ai une liste de nom, je clic sur editer et hop le formulaire pour modifier celui-ci ?
idem pour la suppresion ?

d'avance encore merci de votre aide
splifferwolf est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/02/2008, 13h20   #6
En attente de confirmation mail
 
Inscription : juin 2002
Messages : 6 164
Détails du profil
Informations forums :
Inscription : juin 2002
Messages : 6 164
Points : 6 404
Points : 6 404
Oui, avec DOM comme avec SimpleXML (mais dans ce dernier cas il me semble que la version de PHP est à prendre en compte).

Un exemple pour la modification (réaliser dans le bloc else) :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
$sxml = simplexml_load_file('test.xml');
 
if ($_SERVER['REQUEST_METHOD'] != 'POST' || empty($_POST['personne'])) {
?>
 
<form method="POST">
    Personne :
    <select name="personne">
<?php
foreach ($sxml->personne as $p) {
    printf('<option value="%d">%s</option>', $p['id'], $p->nom);
}
?>
    </select>
    <br />
    <input type="submit" value="Valider" />
</form>
 
<?php
} else if ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST['personne']) && empty($_POST['nom'])) {
?>
 
<form method="POST">
    Nouveau nom : <input type="text" name="nom" />
    <br />
    <input type="submit" value="Valider" />
    <input type="hidden" name="personne" value="<?php echo $_POST['personne']; ?>" />
</form>
 
<?php
} else {
    $res = $sxml->xpath(sprintf('/repertoire/personne[@id = "%d"]', $_POST['personne']));
    $res[0]->nom = utf8_encode($_POST['nom']);
    header('Content-type: text/plain');
    echo $sxml->asXML();
}
La suppression se réalise de la même manière : une fois le noeud ciblé, il suffit de fournir l'objet SimpleXMLElement correspondant à la fonction unset.
julp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/02/2008, 14h21   #7
Membre à l'essai
 
Inscription : novembre 2007
Messages : 88
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : novembre 2007
Messages : 88
Points : 23
Points : 23
merci beaucoup, j'ai compris la méthode à suivre pour enregistré la modification
seulement dans ton exemple, tu le met dans un liste déroulante, moi quand j'ai un tableau avec la liste des nom de type

nom1 | Modifier | Supprimer
nom2 | Modifier | Supprimer

Modifier | Supprimer sont des liens, et passe en variable GET l'attribut id de personne ca donne comme lien "index.php?op=edit&amp;id=1" pour le premier par exemple.

donc quand je clic sur le lien j'arrive sur la case edit() avec le paramètre $_GET['id'] me fournissant l'id à modifier et tombe sur l'input type text mais contenant déjà le nom ( qui doit être modifier ), j'ai donc temps bien que mal essayer de modifier et j'ai ceci dans case edit();
Code :
1
2
3
4
5
6
7
 
$sxml = simplexml_load_file('test.xml');
$personneCible = $sxml->personne->xpath('/repertoire/personne[@id = "' . $_GET['id'] . '"]');
$nom = $personneCible->nom;
echo "<form id=\"edit\" method=\"post\" action=\"index.php?op=saveEdit&amp;id=" . $_GET['id'] . "\">\n"
   . "Modifier le nom --> <input type=\"text\" name=\"nom\" value=\"" . $nom . "\" /> <input type=\"submit\" name=\"send\" value=\"OK\" />\n"
   . "</form>\n";
mais je doit avoir un problème avec l'XPATH que je doit pas vraiment définir correctement, puisque rien ne s'affiche dans l'input comme valeur par defaut, alors que je voudrai qu'il m'affiche dans l'input comme valeur par défaut le nom actuel ( avant la modif ), je sais si c'est clair ce que je raconte.

et enfin ma case saveEdit();
Code :
1
2
3
4
5
6
 
$sxml = simplexml_load_file('test.xml');
$res = $sxml->xpath(sprintf('/repertoire/personne[@id = "%d"]', $_GET['id']));
$res[0]->nom = utf8_encode($_POST['nom']);
header('Content-type: text/plain');
echo $sxml->asXML();
La pas de souci il remplace bien le nom par celui introduit dans l'input, mais je ne comprend pas à quoi correspond le %d

je vous en demande beaucoup, et je vous remercie franchement pour tout ce que vous faite pour m'aider

ps : si vous vous demandez pourquoi je veux l'afficher dans un input, c'est parceque je n'ai pas que <nom> dans <personne> ici j'ai simplifier pour moi comprendre, et j'ai pu appliquer l'ajout de noeud et d'élément à tout le contenu donc maintenant je m'attel à la modification et après à la suppression mais tous ce fait via une variable GET['id'] qui est l'id de <personne>

encore merci mille fois
splifferwolf est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/02/2008, 14h34   #8
En attente de confirmation mail
 
Inscription : juin 2002
Messages : 6 164
Détails du profil
Informations forums :
Inscription : juin 2002
Messages : 6 164
Points : 6 404
Points : 6 404
Activez bien l'affichage de toutes les erreurs : la méthode xpath retourne un tableau. Par conséquent, cette écriture serait plus "juste" :
Code :
$nom = $personneCible[0]->nom;
Au lieu de :
Code :
$nom = $personneCible->nom;
Cependant, il faudrait éventuellement tester le résultat de cette méthode car elle pourrait ne pas retourner de résultat ou échouer (cas à évaluer et qui pourrait se présenter suite à un accès concurrent aux données ou à une saisie manuelle de l'identifiant dans l'URL).

En ce qui concerne l'option de formatage %d (associée à la fonction sprintf) : c'est simplement une habitude de ma part pour avoir un code plus lisible, qui permet aussi d'éviter les casts que l'on emploie souvent dans le cadre des requêtes SQL pour éviter les injections. Si vous préférez, vous pouvez remplacer cette écriture par une concaténation (c'est ce que vous avez fait dans votre premier code) voir une interpolation (ie : "/repertoire/personne[@id = '{$_GET['id']}']").
julp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/02/2008, 14h52   #9
Membre à l'essai
 
Inscription : novembre 2007
Messages : 88
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : novembre 2007
Messages : 88
Points : 23
Points : 23
oui oui Activez bien l'affichage de toutes les erreurs, c'est même devenu sistématique en mode codage.

merci pour vos explication, effectivement une fois coder
Code :
1
2
 
$nom = $personneCible[0]->nom;
celà fonctionne parfaitement, le champ affiche le nom par défaut et la fonction saveEdit
Code :
1
2
 
$res = $sxml->xpath('/repertoire/personne[@id = "' . $_GET['id'] . '"]');
fonctionne parfaitement aussi, merci beaucoup

il ne me reste plus qu'a pouvoir supprimer un noeud, pour ce faire j'ai une case delete(); qui comme pour l'edition récupère la variable $_GET['id'] j'ai donc essayer d'utiliser unset mais rien n'est supprimer je suppose encore un problème de ciblage, voici le code actuel
Code :
1
2
3
4
5
6
 
$sxml = simplexml_load_file('test.xml');
$personneCible = $sxml->personne->xpath('/repertoire/personne[@id = "' . $_GET['id'] . '"]');
unset($personneCible[0]);
header('Content-type: text/plain');
echo $sxml->asXML();
je me suis dit que je devais utiliser le même principe de ciblage que pour la modification soit : $personneCible[0]
Mais apparament je doit encore faire une erreur

Je doit ptet vous soulez avec mes merci mais c'est une question de principe et de respect, donc je vous dit encore merci de votre aide
splifferwolf est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/02/2008, 15h04   #10
En attente de confirmation mail
 
Inscription : juin 2002
Messages : 6 164
Détails du profil
Informations forums :
Inscription : juin 2002
Messages : 6 164
Points : 6 404
Points : 6 404
Désolé, en fait il faut écrire :
Code :
unset($personneCible[0][0]);
Au lieu de :
Code :
unset($personneCible[0]);
julp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/02/2008, 15h12   #11
Membre à l'essai
 
Inscription : novembre 2007
Messages : 88
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : novembre 2007
Messages : 88
Points : 23
Points : 23
houraaa ca fonctionne :p grâce à vous je peux Ajouter/modifier/Suprrimer un noeud

j'ai toute fois encore une toute petite question
pour la suppression nous devons utiliser
$personneCible[0][0]
Alors que pour la modification nous utilison
$personneCible[0]
pourtant c'est exactement la même manipulation pour la modification et pour la suppression, pourriez-vous m'expliquer pourquoi nous avons du rajouter une clé [0] pour la suppression et pas pour la modification ?

Voilà c'est ma toute dernière question, après ce sujet sera résolut grâce à vous et vous en remercie encore
splifferwolf est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/02/2008, 16h01   #12
En attente de confirmation mail
 
Inscription : juin 2002
Messages : 6 164
Détails du profil
Informations forums :
Inscription : juin 2002
Messages : 6 164
Points : 6 404
Points : 6 404
Je l'ignore mais cela semble propre à la fonction unset pour un résultat d'une expression XPath. Cela peut être dû à la manière dont sont représentés en interne les éléments (les développeurs ont pu reprendre la structure du document, c'est à dire que chaque élément du résultat pourrait être plus complexe qu'il n'y paraît au sens que l'objet SimpleXMLElement ne correspondrait pas directement à un élément. Pour illustrer, prenez l'exemple de $sxml->personne qui représente l'ensemble des éléments personne, fils de la racine).
julp est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 07h55.


 
 
 
 
Partenaires

Hébergement Web