2009-03-12 2 views
0

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

$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, но я не могу изменить фактическое имя элемента целевого элемента.

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

Кто-нибудь?

ответ

2

Использование replaceChild вместо AppendChild/RemoveChild.

+0

Ваше предложение сработало достаточно хорошо. Хотя мне пришлось использовать «importNode» в сочетании с «appendChild» и «cloneNode». Прекрасно работает! Приветствия! –

+0

Если вы используете importNode, вам также не нужно клонировать его, importNode, по необходимости, клонирует узел. – AnthonyWJones

0

Поиск, если элемент $ имеет следующую строку перед удалением, если в этом случае 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, большой живость как же я скучаю в тот момент :)

+0

Герм, я дам ему вихрь. Спасибо! –

 Смежные вопросы

  • Нет связанных вопросов^_^