Использование DOMXPath для замены узла с сохранением его положения

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

  •  22-07-2019
  •  | 
  •  

Вопрос

Итак, прошлой ночью мне пришла в голову небольшая идея создать вспомогательный класс для DOMDOCUMENT, который в некоторой степени имитирует способность jQuery манипулировать DOM строкой на основе HTML или XML.Вместо css-селекторов используется XPath.Например:

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

Это привело бы к вызову функции обратного вызова на каждом результирующем узле.К сожалению, версия PHP < 5.3.x не поддерживает лямбда-функции или замыкания, поэтому на данный момент я вынужден сделать что-то более похожее на это:

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

На данный момент все работает отлично, и я думаю, что этот проект был бы полезен многим людям, но я застрял с одной из функций.Я пытаюсь имитировать метод 'replace' 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, но я не могу изменить фактическое имя элемента целевого элемента.

Отражение может быть возможным, но должен быть более простой способ сделать это.

Кто-нибудь?

Это было полезно?

Решение

Используйте replaceChild вместо appendChild/removeChild.

Другие советы

Посмотрите, имеет ли $element следующую привязку перед удалением, если это так, сделайте вставку перед этим следующим побратимом, в противном случае просто добавьте.

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

Хотя совершенно непроверенный.

Или как предположил Энтони Джонс Заменить ребенка , большой умф как же я упустил этот момент :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top