php5.0.3 dom - не работает removeChild

slach

Новичок
php5.0.3 dom - не работает removeChild

бред какой то, объясните человеку

имею XML следующего содержания
PHP:
<?xml version="1.0" encoding="windows-1251"?>
<root>
<something_for_remove/>
<something_for_remove/>
<something_for_remove/>
</root>
обрабатываю его вот таким макаром
PHP:
<?php

$dom= new DOMDocument();
$dom->load('removeChild.test.xml');

foreach($dom->documentElement->childNodes as $node) {
  $node->parentNode->removeChild($node);
}
echo '<hr>$dom->saveXML()<hr>'.htmlspecialchars($dom->saveXML());
?>
на выходе все равно получаю
PHP:
<?xml version="1.0" encoding="windows-1251"?>
<root>
<something_for_remove/>
<something_for_remove/>
<something_for_remove/>
</root>
почему something_for_remove не удаляются ?

-~{}~ 18.01.05 15:42:

попробовал без foreach
PHP:
while($dom->documentElement->firstChild) {
$dom->documentElement->firstChild->parentNode->removeChild($dom->documentElement->firstChild);
}
работает

неужели дело в foreach ? он копии объекта чтоли создает ???


но что тогда делать если надо пройтись по nodeset вызванном через XPath ?
 

chameleon

Новичок
предположительно, если xml с разметкой то убиваешь пустых чайлдов.

-~{}~ 18.01.05 14:54:

хотя гоню, должен всех убивать :)
 

slach

Новичок
прошу прощения за беспокойство

проблема с XPath решилась
PHP:
$xpath = new DOMXPath($dom);
$nodelist = $xpath->query('/root');
for ($i=0;$i<$nodelist->length;$i++) {
  echo '<br>$nodelist->length='+$nodelist->length;
  $nodelist->item($i)->parentNode->removeChild($nodelist->item($i));
}
echo '<hr>$dom->saveXML()<hr>'.htmlspecialchars($dom->saveXML());
вывод на будующее нельзя применять foreach для коллекций объектов потому что будут копии
 

tony2001

TeaM PHPClub
не поверите, но вот с таким XML:
Код:
<?xml version="1.0" encoding="windows-1251"?> 
<root><something_for_remove/> 
<something_for_remove/> 
<something_for_remove/> 
</root>
всё работает.
обратите внимание на отсутствие \n после <root>.
 

slach

Новичок
бред какой то... у тебя работает именно для foreach ???
или для while по коллекции childNodes ?

-~{}~ 18.01.05 17:39:

версия libxml какая ?

-~{}~ 18.01.05 17:55:

в случае если убрать \n то удаляется только ПЕРВЫЙ something_for_remove
 

[DAN]

Старожил PHPClub
>в случае если убрать \n то удаляется только ПЕРВЫЙ something_for_remove
Наблюдается такое же поведение в случае с foreach. C while удаляются все узлы.

PHP Version 5.0.3
DOM/XML API Version 20031129
libxml Version 2.5.4
 

slach

Новичок
если в этом коде закоментировать строку с removeChild
тогда ТРИ РАЗА выводится nodeType=1
если раскоментировать, тогда один раз =))

БАГ ?
PHP:
foreach($dom->documentElement->childNodes as $node) {
  echo '<br> $node->nodeType='.$node->nodeType;
  $node->parentNode->removeChild($node);
}
 

[DAN]

Старожил PHPClub
>нельзя применять foreach для коллекций объектов потому что будут копии
Но ведь первый элемент все-таки убивается. Пусть даже он текстовый нод "\n".

-~{}~ 18.01.05 16:04:

У меня есть мысль, что где-то сбрасываются указатели в foreach.
Ведь мы убиваем нод в документе, по которому итерируемся. Это смахивает на ситуацию с unset-ом элементов массива, по которому мы пробегаемся в foreach.

-~{}~ 18.01.05 16:06:

Либо действительно создается копия объекта. Но тогда вопрос - почему первый элемент все-таки удаляется?
 

slach

Новичок
http://bugs.php.net/bug.php?id=31089


foreach should not be used when adding/appending/removing any of the top level nodes in the nodelist.

top level nodes видимо уже непричем но в общем foreach нельзя использовать для Live Object Collection ... ;)
 

slach

Новичок
1) foreach($dom->documentElement->childNodes as &$node) {

удаляет все равно тлько первый елемент

2) $dom->preserveWhiteSpace=false;
перед $dom->load
тоже не помогает

в общем то еще DIMA в свое время предлагал отказываться от foreach под предлогом ТОРМОЗНУТОСТИ =)
 
Сверху