Свойство php DOMDocument nodeName, возвращающее «#text» с именем узла - PullRequest
11 голосов
/ 06 марта 2012

Я хочу извлечь содержимое тела html-страницы вместе с tagNames ее дочернего элемента.Я взял пример HTML, как это:

<html>
<head></head>
<body>
<h1>This is H1 tag</h1>
<h2>This is H2 tag</h2>
<h3>This is H3 tag</h3>
</body>
</html>

Я реализовал код php, как показано ниже, и он работает нормально.

$d=new DOMDocument();
$d->loadHTMLFile('file.html');
$l=$d->childNodes->item(1)->childNodes->item(1)->childNodes;
for($i=0;$i<$l->length;$i++)
{
echo "<".$l->item($i)->nodeName.">".$l->item($i)->nodeValue."</".$l->item($i)->nodeName.">";
}

Этот код работает отлично, но когда япопытался сделать это, используя цикл foreach вместо цикла for, свойство nodeName возвращало '#text' с каждым фактическим именем узла.Вот этот код

$l=$d->childNodes->item(1)->childNodes->item(1)->childNodes;
foreach ($l as $li) {
    echo $li->childNodes->item(0)->nodeName."<br/>";
}

Почему так?

Ответы [ 3 ]

16 голосов
/ 21 марта 2014

Когда у меня возникла эта проблема, она была исправлена ​​следующим образом.

$xmlDoc = new DOMDocument();
$xmlDoc->preserveWhiteSpace = false; // important!

Вы можете отследить ваш $ node-> nodeType, чтобы увидеть разницу. Я получаю 3, 1, 3, хотя был только один узел (дочерний). Выключите пробел, и теперь я просто получаю 1.

GL.

16 голосов
/ 06 марта 2012

В DOM все является «узлом». Не только элементы (теги); комментарии и текст между элементами (даже если это просто пробелы или переводы строк, что, как кажется, имеет место в вашем примере) также являются узлами. Поскольку текстовые узлы не имеют фактического имени узла, оно заменяется #text, чтобы указать, что это особый вид узла.

Видимо, текстовые узлы не учитываются при ручном выборе дочерних узлов с помощью метода item, но включаются при итерации по DOMNodeList. Я не уверен, почему класс ведет себя так, кто-то другой должен будет ответить на этот вопрос.

Кроме nodeName и nodeValue, DOMNode также имеет свойство nodeType. Проверяя это свойство в отношении определенных констант , вы можете определить тип узла и таким образом отфильтровать нежелательные узлы.

4 голосов
/ 15 января 2014

Я немного опаздываю к этому, но лучшее решение для меня было другим.Проблема в том, что узел TEXT не знает своего имени, но его родитель делает все, что вам нужно знать, это попросите его у родителя nodeValue, чтобы получить ключ.

$dom = new DOMDocument();
$dom->loadXML($stringXML);
$valorizador = $dom->getElementsByTagName("tagname");
foreach ($valorizador->item(0)->childNodes as $item) {
  $childs = $item->childNodes;
  $key = $item->nodeName;
  foreach ($childs as $i) {
     echo $key." => ".$i->nodeValue. "\n";
  }
}
...