2009-07-20 9 views
5

J'ai besoin de supprimer des éléments d'un fichier XML en utilisant PHP. Cela se fera via ajax et j'ai besoin de trouver l'élément XML via un attribut.PHP - Supprimer l'élément XML

Ceci est mon fichier XML

<?xml version="1.0" encoding="utf-8"?> 
<messages> 
    <message time="1248083538"> 
     <name>Ben</name> 
     <email>Ben's Email</email> 
     <msg>Bens message</msg> 
    </message> 
    <message time="1248083838"> 
     <name>John Smith</name> 
     <email>[email protected]</email> 
     <msg>Can you do this for me?</msg> 
    </message> 
</messages> 

Donc ce que je dirais est quelque chose comme supprimer l'élément où le temps est égal à 1248083838.

Ive été en utilisant XML simple jusqu'à présent et je viens réalisé qu'il peut tout faire sauf supprimer des éléments.

Alors, comment ferais-je cela?

Répondre

7

Vous pouvez utiliser les classes DOM en PHP. (http://us3.php.net/manual/en/intro.dom.php).

Vous aurez besoin de lire le document XML en mémoire, utiliser les classes DOM pour effectuer des manipulations, puis sauvegarder le code XML si nécessaire (en http ou en fichier). DOMNode est un objet qui contient des fonctions de suppression (pour répondre à votre question).

Il est un peu plus compliqué que SimpleXML, mais une fois que vous y habituer, il est beaucoup plus puissant

(semi-prise d'un exemple de code à php.net)

<?php 

$doc = new DOMDocument; 
$doc->load('theFile.xml'); 

$thedocument = $doc->documentElement; 

//this gives you a list of the messages 
$list = $thedocument->getElementsByTagName('message'); 

//figure out which ones you want -- assign it to a variable (ie: $nodeToRemove) 
$nodeToRemove = null; 
foreach ($list as $domElement){ 
    $attrValue = $domElement->getAttribute('time'); 
    if ($attrValue == 'VALUEYOUCAREABOUT') { 
    $nodeToRemove = $domElement; //will only remember last one- but this is just an example :) 
    } 
} 

//Now remove it. 
if ($nodeToRemove != null) 
$thedocument->removeChild($nodeToRemove); 

echo $doc->saveXML(); 
?> 

Cela devrait donner vous avez un peu une idée sur la façon de supprimer l'élément. Il imprimera le XML sans ce noeud. Si vous voulez l'envoyer au fichier, écrivez simplement la chaîne dans le fichier.

+0

Hmm ... Je suis un peu dépassée par tout. Pourriez-vous expliquer un peu plus? –

+0

Bien sûr. Je vais modifier. –

+0

Je n'ai pas eu l'occasion de vérifier les erreurs de syntaxe mineures - mais cela devrait vous donner quelque chose comme ce dont vous avez besoin. Je recommande de ne pas retirer l'enfant dans le forloop lui-même, car il dérange le compteur interne de la foreach. –

2

vous devriez être en mesure de supprimer des nœuds à travers les fonctions DOM.

http://www.w3schools.com/Dom/dom_nodes_remove.asp

+0

Toujours pas sûr de savoir comment supprimer en fonction de l'attribut bien –

+0

Il suffit de faire la partie de l'attribut de votre algorithme de recherche. Rester simple. – joejoeson

9

Dave Morgan est correct en ce que les classes DOM sont plus puissants, mais si vous voulez coller avec SimpleXML, essayez d'utiliser la fonction unset() sur un noeud. Par exemple. unset ($ simpleXMLDoc-> node1-> child1), qui sera supprimé du fichier XML.

+0

Je n'ai pas essayé de le faire, mais la logique dicte que cela devrait fonctionner correctement. Ça a l'air d'être un peu rapide, mais un travail correct pour moi. –

+3

Ne me semble pas rapide-n-sale. Cela ressemble au codage normal. – Tjorriemorrie

1

Même si SimpleXML ne dispose pas d'une manière détaillée pour supprimer des éléments, vous pouvez supprimer des éléments de SimpleXML en utilisant PHP unset(). La clé pour y arriver est de réussir à cibler l'élément désiré. Au moins une façon de faire le ciblage consiste à utiliser l'ordre des éléments. D'abord trouver le numéro d'ordre de l'élément que vous souhaitez supprimer (par exemple avec une boucle), puis retirez l'élément:

$target = false; 
$i = 0; 
foreach ($xml->message as $m) { 
    if ($m['time']=='1248083838') { $target = $i; break; } 
    $i++; 
} 
if ($target !== false) { 
    unset($xml->message[$target]); 
} 

Vous pouvez même supprimer plusieurs éléments à cela, en stockant le numéro de commande d'éléments cibles dans un tableau. N'oubliez pas de faire la suppression dans l'ordre inverse (array_reverse($targets)), car la suppression d'un élément réduit naturellement le numéro de commande des éléments qui le suivent.

Certes, c'est un peu un hackaround, mais il semble bien fonctionner.