DOMXPathを使用して、ノードの位置を維持しながらノードを置き換える

StackOverflow https://stackoverflow.com/questions/640815

  •  22-07-2019
  •  | 
  •  

質問

Ok、それで、先日、jQueryがHTMLまたはXMLベースの文字列のDOMを操作する能力をある程度模倣するDOMDOCUMENTのヘルパークラスを作成するという、このちょっとしたアイデアを思いつきました。 CSSセレクターの代わりに、XPathが使用されます。例:

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

これにより、すべての結果ノードでコールバック関数が呼び出されます。残念ながら、PHPバージョン<!> lt; 5.3.xはラムダ関数またはクロージャーをサポートしていないため、当面はもう少しこのようなことをする必要があります。

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

現時点ではすべてがうまく機能しており、このプロジェクトは多くの人々に役立つと思いますが、機能の1つにとどまっています。 jQueryの「置換」メソッドを模倣しようとしています。次のコードを使用して、次のメソッドを適用することでこれを簡単に実現できます。

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

このメソッドの背後にあるコードは次のとおりです。

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

    return $this;
}

今、これは動作します。結果の要素はすべて、$ Contentのクローンバージョンに置き換えられます。問題は、親ノードの子のリストの下部にそれらを追加することです。問題は、DOMの元の位置を保持したまま、この要素のクローンを作成して他の要素を置き換える方法です。

私は、交換するノードのリバースエンジニアリングについて考えていました。基本的に、$ Contentから値、属性、要素名をコピーしますが、ターゲット要素の実際の要素名を変更することはできません。

反射は可能性がありますが、これを行う簡単な方法があります。

誰ですか?

役に立ちましたか?

解決

appendChild / removeChildの代わりにreplaceChildを使用します。

他のヒント

削除する前に$ elementにnextsibblingがある場合はルックアップし、そうであればinsertBeforeを実行し、そうでない場合は単純に追加します。

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

ただし、完全にテストされていません。

またはAnthonyWJonesが提案したように replaceChild 、大きな oomph どうしてその瞬間を逃したのか:)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top