DOMXPathを使用して、ノードの位置を維持しながらノードを置き換える
-
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 どうしてその瞬間を逃したのか:)