如何通过dom过滤空节点?

时间:2013-02-19 05:18:36

标签: php dom

我想只获取一些真实文本子元素节点的元素(不是空格或 等)。

我尝试了以下html:

<p>&nbsp;</p>
<div>&nbsp;</div>

到目前为止,我已尝试过这段代码:

$dom = new DOMDocument;

$dom->loadHTML($html);
$dom->preserveWhiteSpace = false;

$i = 0;
while (is_object($html_synch = $dom->getElementsByTagName("body")->item($i))) {
    foreach ($html_synch->childNodes as $node) {
        if ($node->nodeName != "script" && $node->nodeName != "style" &&
                XML_COMMENT_NODE != $node->nodeType):
            get_children($node);
        endif;
    }
    $i++;
}

然后在get_children函数中我使用此代码用&nbsp;过滤空节点或节点:

foreach ($node->childNodes as $child) :
    if (trim($child->nodeValue) != ""):
        echo $child->nodeValue;  // it returns Â
        echo $child->nodeName;   // it returns #text
        array_push($children_type, $child->nodeType);
    endif;
endforeach;
print_r($children_type);

#text  and Array ( [0] => 3 )返回<p>&nbsp;</p>。那我怎么过滤它们呢?我知道#text是文本的特殊节点名称。

Link to demo :

1 个答案:

答案 0 :(得分:1)

事先得到一些解释:原因是,您看到的是您的HTML文档被视为UTF-8,但您将其显示为ISO 8859-1。非中断空间&nbsp;被编码为UTF-8中的两个字节:0xC2 0xA0。在ISO 8859-1中,它只是0xA0,而0xC2表示À

现在,您可以在trim()中指定应修剪哪些字符,以便您可以包含不间断的空格(默认字符也必须明确添加):

if (trim($child->nodeValue, " \n\r\t\0\xC2\xA0") !== ""):
    // value is not empty

目前你的功能没有过滤,所以我不确定你想要对这些项目做什么。但其余部分应该很简单,例如:

  • 计算节点类型不是文本值不为空的子项
  • if count&gt; 0,保持元素

更新

你的代码的其余部分有点粗糙,所以我做了一个最小的工作示例:

测试代码:

$html = <<<HTML
<body>
 <div>
  <p>not-empty</p>
  <p>&nbsp;</p>
  <div>&nbsp;</div>
 </div>
</body>
HTML;


$dom = new DOMDocument;

$dom->loadHTML($html);
$dom->preserveWhiteSpace = false;

$xpath = new DOMXPath($dom);

foreach ($xpath->query('//*') as $node) {
  if (!count($node->childNodes) || trim($node->nodeValue, " \n\r\t\0\xC2\xA0")==='') {
    echo 'to filter: ' . $node->getNodePath() . "\n";
  }
}

测试输出:

to filter: /html/body/div/p[2]
to filter: /html/body/div/div

<强> Link to demo