2010-06-20 6 views
0

je xml, structuré comme celui-ciparent suppression du nœud

<element> 
    <x> 
     <y> 
      <z>Value</z> 
     </y> 
    </x> 
</element> 

je sélectionne tous <z> -tags de xml par cette requête XPath - //*[name()='z'].

Ensuite, je travaille avec chaque nœud de recherche, et s'il ne répond pas à certaines exigences, il faut supprimer toute la X-tag (grand-père de, si vous voulez :)).

foreach ($x->query("//*[name()='z']") as $elm) 
{ 

if ($elm !== good) 
{ 

//need to delete whole X-tag here 

} 


} 

Alors, comment puis-je faire cela?

Répondre

1

Peut-être

$elm->parentNode->parentNode->parentNode-> 
    removeChild($elm->parentNode->parentNode); 

Par ailleurs, vous pouvez utiliser

foreach ($x->query("//z") as $elm) 

à la place.

+0

oui, je sais que sur l'utilisation de "parentNode". C'est très bizarre, mais ce code '$ elm-> parentNode-> parentNode-> parentNode-> removeChild ($ elm-> parentNode-> parentNode);' briser le foreach. Par exemple, j'ai six '$ elm', où 4ème et 6ème" pas bon ". Quand la boucle foreach arrive au 4ème élément, elle supprime tout le "X" -tag, mais alors, la boucle est break. Les 5ème et 6ème éléments sont ignorés. C'est très intéressant, parce que ce code '$ elm-> parentNode-> removeChild ($ elm);' - fonctionne parfaitement. En fait, c'est pourquoi j'ai écrit ce post. Des idées? Peut-être que c'est bug php? – nukl

+0

hein, il a travaillé avec ce code: '$ temp1 = $ elm-> parentNode-> parentNode-> parentNode; $ temp2 = $ elm-> parentNode-> parentNode; $ temp1-> removeChild ($ temp2); ' – nukl

+0

@cru Vous avez raison, je dirais même que vous devriez différer le retrait jusqu'à la fin de la boucle. – Artefacto

0

Je pense que vous mélangez les méthodes de deux classes ensemble.

SimpleXMLElement::removeChild n'existe pas (cela fait partie de DOMNode). Malheureusement, DOMDocument::xpath n'existe pas, vous ne pouvez donc pas utiliser l'un ou l'autre sans modifier votre code.

J'ai choisi DOMDocument en raison de la simplicité de votre sélection DOM (juste besoin des éléments par le nom de tag), et voici mes résultats:

<?php 

    $bad = 'Value'; 
    $doc = DOMDocument::load('./xpath_del.xml') or die('Failed parsing XML'); 
    $x = $doc->getElementsByTagName('x'); 

    for ($i = 0; $i < $x->length; ++$i) { 
     $z = $x->item($i)->getElementsByTagName('z'); 
     for ($j = 0; $j < $z->length; ++$j) { 
      if ($bad === $z->item($i)->nodeValue) { 
       $x->item($i)->parentNode->removeChild($x->item($j)); 
       break; 
      } 
     } 
    } 

?> 

Ainsi, en utilisant la conversion à SimpleXMLElement à des fins de débogage (parce que je « m trop paresseux pour écrire une méthode pour traverser les DOMNode s dans le DOMDocument):

var_dump(simplexml_import_dom($doc)); 

à la sortie de la structure DOMDocument avant et après. Rappelez-vous, si c'est pour un site à fort trafic, je recommande absolument de ne pas laisser ce code de débogage (mais cela ne vous importera peut-être pas).

Quoi qu'il en soit, voici les résultats avant:

object(SimpleXMLElement)#2 (1) { 
    ["x"]=> 
    object(SimpleXMLElement)#3 (1) { 
    ["y"]=> 
    object(SimpleXMLElement)#4 (1) { 
     ["z"]=> 
     string(5) "Value" 
    } 
    } 
} 

Et après:

object(SimpleXMLElement)#5 (0) { 
} 

Essayez par vous-même,;)

+0

il suffit de relire la question, reformatage, maintenez –

+0

cela suppose également que vous avez un fichier nommé "xpath_del.xml "avec la même structure que vous avez décrit dans le même répertoire, btw ... –

Questions connexes