php DOMDocument nodeName属性,返回带有nodeName的'#text'

时间:2012-03-06 19:22:37

标签: php dom html-parsing

我想提取html页面正文的内容以及其子页面的tagNames。我举了一个像这样的例子:

<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'和每个实际的nodeName。 这是代码

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

为什么会这样?

3 个答案:

答案 0 :(得分:16)

在DOM中,一切都是“节点”。不仅仅是元素(标签);元素之间的注释和文本(即使它只是空格或换行符,在您的示例中似乎就是这种情况)也是节点。由于文本节点没有实际的节点名称,因此用#text代替它表示它是一种特殊的节点。

显然,当使用item方法手动选择子节点时,文本节点会被遗漏,但在迭代DOMNodeList时会包括在内。我不确定为什么班级表现得像这样,其他人将不得不回答这个问题。

nodeNamenodeValue旁边,DOMNode也有nodeType属性。通过针对certain constants检查此属性,您可以确定节点的类型,从而过滤掉不需要的节点。

答案 1 :(得分:16)

当我遇到这个问题时,通过执行以下操作解决了这个问题。

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

您可以找出$ node-&gt; nodeType来查看差异。即使只有一个节点(孩子),我得到3,1,3。关闭白色空间,现在我得到1。

GL

答案 2 :(得分:4)

我来晚了一点,但对我来说最好的解决方案是不同的。问题是,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";
  }
}