PHP DOM - подсчет дочерних узлов?


Фрагмент HTML-кода #1

<div>
</div>
<div>
    <h1>headline</h1>
</div>

Фрагмент HTML-кода #2

<div></div>
<div><h1>headline</h1></div>

PHP-код

$doc = new DOMDocument();
$doc->loadHTML($x);
$xpath = new DOMXpath($doc);
$divs = $xpath->query("//div");

foreach ($divs as $div) echo $div->childNodes->length,"<br />";

Вывод с помощью фрагмента $x = #1
1
3

Вывод с помощью фрагмента $x = #2
0
1

Смотрите рабочую демонстрацию: http://codepad.viper-7.com/11BGge

Мои вопросы
1. Как это может быть?
2. Как правильно подсчитывать дочерние узлы с помощью DOM?

РЕДАКТИРОВАТЬ:
как сказал Шелковый огонь, пустое пространство считается текстовым узлом. Я установил

$doc->preserveWhiteSpace = false;

Но результаты все те же: http://codepad.viper-7.com/bnG5io

Есть идеи?

 9
Author: michi, 2013-05-10

3 answers

Просто посчитайте нетекстовые узлы в своем цикле:

$count = 0;
foreach($div->childNodes as $node)    
  if(!($node instanceof \DomText))      
    $count++;

print $count;

Использование xpath:

$nodesFromDiv1 = $xpath->query("//div[1]/*")->length;
$nodesFromDiv2 = $xpath->query("//div[2]/*")->length;

Чтобы удалить пустые текстовые узлы, когда preserveWhiteSpace=false не работает (как я предложил в чате):

$textNodes = $xpath->query('//text()');

foreach($textNodes as $node)
  if(trim($node->wholeText) === '')
    $node->parentNode->removeChild($node);
 6
Author: nice ass, 2013-05-09 22:19:23

Пробел считается узлом, потому что это узел text() (DOMText).

Вы можете сделать эту работу, изменив свой цикл foreach:

foreach ($divs as $div) {
    echo $div->childNodes->length - $xpath->query('./text()', $div)->length, '<br>';
}
 3
Author: silkfire, 2013-05-09 23:31:37

Firefox, Chrome и большинство других браузеров будут рассматривать пустые пробелы или новые строки как текстовые узлы, Internet Explorer - нет.Проверять Здесь

 0
Author: Yogus, 2013-05-09 21:31:57