Question

Ok, alors j’ai eu cette jolie petite idée l’autre soir de créer une classe d’aide pour DOMDOCUMENT qui imite, dans une certaine mesure, la capacité de jQuery à manipuler le DOM d’une chaîne HTML ou XML. Au lieu de sélecteurs css, XPath est utilisé. Par exemple:

$Xml->load($source)
    ->path('//root/items')
    ->each(function($Context)
    {
        echo $Context->nodeValue;
    });

Ceci invoquerait une fonction de rappel sur chaque nœud résultant. Malheureusement, la version PHP & Lt; 5.3.x ne supporte pas les fonctions lambda ni les fermetures, je suis donc obligé de faire quelque chose d'un peu plus semblable à celui-ci pour le moment:

$Xml->load($source)
    ->path('//root/items')
    ->walk('printValue', 'param1', 'param2');

Tout fonctionne très bien en ce moment et je pense que ce projet serait utile à beaucoup de gens, mais je suis coincé avec l'une des fonctions. Je tente d'imiter la méthode 'replace' de jQuery. En utilisant le code suivant, je peux y arriver assez facilement en appliquant la méthode suivante:

$Xml->load($source)
    ->path('//root/items')
    ->replace($Xml->createElement('foo', 'bar')); // can be an object, string or XPath pattern

Le code derrière cette méthode est:

public function replace($Content)
{
    foreach($this->results as $Element)
    {
        $Element->parentNode->appendChild($Content->cloneNode(true));
        $Element->parentNode->removeChild($Element);
    }

    return $this;
}

Maintenant, cela fonctionne. Il remplace chaque élément résultant par une version clonée de $ Content. Le problème est que cela les ajoute au bas de la liste des enfants du nœud parent. La question est de savoir comment cloner cet élément pour remplacer d'autres éléments tout en conservant la position d'origine dans le DOM.

Je pensais à la rétro-ingénierie du nœud que je devais remplacer. Fondamentalement, copier les valeurs, les attributs et le nom de l'élément à partir de $ Content, mais je ne peux pas changer le nom réel de l'élément cible.

La réflexion pourrait être une possibilité, mais il doit y avoir un moyen plus facile de le faire.

Quelqu'un?

Était-ce utile?

La solution

Utilisez replaceChild au lieu de appendChild / removeChild.

Autres conseils

Recherchez si $ element a un changement avant de le supprimer, le cas échéant, insérez-le avant ce prochain frère, sinon, ajoutez simplement.

public function replace($Content)
{
        foreach($this->results as $Element)
        {
                if ($Element->nextSibling) {
                    $NextSiblingReference = $Element->nextSibling;
                    $Element->parentNode->insertBefore($Content->cloneNode(true),$NextSiblingReference);
                }
                else {
                    $Element->parentNode->appendChild($Content->cloneNode(true));   
                }
                $Element->parentNode->removeChild($Element);
        }

        return $this;
}

Totalement non testé cependant.

Ou comme AnthonyWJones a suggéré replaceChild , grand oomph comment ai-je raté ce moment:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top