Domanda

Ok, quindi l'altra sera ho avuto questa bella idea di creare una classe di supporto per DOMDOCUMENT che imiti, in una certa misura, la capacità di jQuery di manipolare il DOM di una stringa basata su HTML o XML. Invece di selettori CSS, viene utilizzato XPath. Ad esempio:

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

Questo invocherebbe una funzione di callback su ogni nodo risultante. Sfortunatamente, la versione di PHP & Lt; 5.3.x non supporta le funzioni o le chiusure lambda, quindi per il momento sono costretto a fare qualcosa di più simile a questo:

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

Al momento tutto funziona alla grande e penso che questo progetto sarebbe utile a molte persone, ma sono bloccato con una delle funzioni. Sto tentando di imitare il metodo di "sostituzione" di jQuery. Utilizzando il seguente codice, posso farlo abbastanza facilmente applicando il seguente metodo:

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

Il codice dietro questo metodo è:

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

    return $this;
}

Ora funziona. Sostituisce ogni elemento risultante con una versione clonata di $ Content. Il problema è che li aggiunge in fondo all'elenco dei figli del nodo padre. La domanda è: come posso clonare questo elemento per sostituire altri elementi, pur mantenendo la posizione originale nel DOM?

Stavo pensando di decodificare il nodo che avrei dovuto sostituire. Fondamentalmente, copiando valori, attributi e nome dell'elemento da $ Content, ma non riesco a cambiare il nome dell'elemento effettivo dell'elemento target.

La riflessione potrebbe essere una possibilità, ma deve esserci un modo più semplice per farlo.

Chiunque?

È stato utile?

Soluzione

Usa replaceChild invece di appendChild / removeChild.

Altri suggerimenti

Cerca se $ element ha un nextsibbling prima di rimuoverlo, in tal caso fai un insertPrima che il prossimo fratello altrimenti semplicemente accoda.

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;
}

Totalmente non testato però.

O come suggerito AnthonyWJones sostituisciBambino , grande oomph come mi sono perso quel momento :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top