2009-03-12 8 views
0

Ok, also hatte ich diese nette kleine Idee die andere Nacht eine Hilfsklasse für DOMDOCUMENT zu erstellen, die gewissermaßen jQuerys Fähigkeit nachahmt, das DOM eines HTML oder XML zu manipulieren -basierte Zeichenfolge. Anstelle von CSS-Selektoren wird XPath verwendet. Zum Beispiel:Verwenden von DOMXPath zum Ersetzen eines Knotens unter Beibehaltung seiner Position

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

Dies würde eine Callback-Funktion auf jedem resultierenden Knoten aufrufen. Leider PHP Version 5.3.x < nicht Lambda-Funktionen oder Schließungen nicht unterstützt, so dass ich etwas ein bisschen mehr wie dies für den Augenblick zu tun gezwungen:

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

Alles funktioniert groß im Moment, und Ich denke, dass dieses Projekt für viele Leute nützlich sein würde, aber ich stecke mit einer der Funktionen fest. Ich versuche, die "Ersetzen" -Methode von jQuery nachzuahmen. Unter Verwendung des folgenden Codes kann ich dies erreichen ganz einfach durch die folgende Methode anwenden:

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

Der Code hinter dieser Methode ist:

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

    return $this; 
} 

Nun, dies funktioniert. Es ersetzt jedes resultierende Element durch eine geklonte Version von $ Content. Das Problem besteht darin, dass sie am unteren Rand der Liste der untergeordneten Knoten des übergeordneten Knotens hinzugefügt werden. Die Frage ist, wie klon ich dieses Element, um andere Elemente zu ersetzen, während ich immer noch die ursprüngliche Position im DOM behalte?

Ich dachte über das Reverse-Engineering des Knotens nach, den ich ersetzen sollte. Im Prinzip kopieren Sie Werte, Attribute und Elementnamen aus $ Content, aber ich kann den tatsächlichen Elementnamen des Zielelements nicht ändern.

Reflektion könnte eine Möglichkeit sein, aber es muss einen einfacheren Weg geben, dies zu tun.

Jeder?

Antwort

2

Verwenden replaceChild statt appendChild/removeChild.

+0

Ihr Vorschlag hat ganz gut funktioniert. Allerdings musste ich "ImportNode" in Kombination mit "appendChild" und "cloneNode" verwenden. Funktioniert wunderbar! Prost! –

+0

Wenn Sie importNode verwenden, müssen Sie es auch nicht klonen, da ImportNode den Knoten unbedingt klonen muss. – AnthonyWJones

0

Lookup, wenn $ Element hat eine Nexsibbling vor dem Entfernen, wenn ja, ein Insert Vor dem nächsten Geschwister sonst einfach anhängen.

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

Völlig ungetestet obwohl.

Oder wie AnthonyWJones replaceChild vorgeschlagen, große Pep wie vermißte ich diesen Moment :)

+0

Hrm, ich werde es einen Wirbel geben. Danke! –

Verwandte Themen