删除没有子DOM的元素DOM PHP

时间:2015-04-18 07:23:26

标签: php html domdocument

我想从字符串中删除所有空的<a>标记。

这样:

<a href="http://www.google.com"></a>

而不是:

<a href="http://www.google.com">Not empty</a>

然而:

<a href="http://www.google.com"><img src="puppy.jpg" alt="Not empty"></a>

也被删除了。

编辑: 基本上图像被删除,因为它们似乎有一个空的nodeValue。我想保留图像。当<a>标记之间有图像时,为什么nodeValue返回空?

这是我的尝试:

<?php
$content_before='
so:
<a href="http://www.google.com"></a>

and not:
<a href="http://www.google.com">Not empty</a>

However:
<a href="http://www.google.com"><img src="puppy.jpg" alt="Not empty"></a>
';
$dom=new domDocument;
@$dom->loadHTML($content_before);
$dom->preserveWhiteSpace = true;

$anchors=$dom->getElementsByTagName('a');
foreach($anchors as $a)
{
    $as[] = $a;
}
foreach($as as $a)
{
    $nodevalue=$a->nodeValue;
    $nodevalue=trim($nodevalue);

    if(empty($nodevalue)&&is_object($a))
    {
        #remove links without nodevalues
        $a->parentNode->removeChild($a);
    }
}
$content=$dom->saveHTML();
echo 'before:<br><textarea>'.$content_before.'</textarea>'; 
echo 'after<br><textarea>'.$content.'</textarea>';  

#what $content becomes:
$content='
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p>so:


and not:
<a href="http://www.google.com">Not empty</a>

However:
</p></body></html>';

#What I want it to be:
$content_after='
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p>so:

and not:
<a href="http://www.google.com">Not empty</a>

However:
<a href="http://www.google.com"><img src="puppy.jpg" alt="Not empty"></a>
</p></body></html>';
?>

2 个答案:

答案 0 :(得分:1)

另一种方法是使用xpath查询,然后获取所有没有/空子元素的元素。之后,使用回归删除所有这些元素:

$dom = new DomDocument;
@$dom->loadHTML($content_before);
$dom->preserveWhiteSpace = true;
$xpath = new DOMXpath($dom);

$empty_anchors = $xpath->evaluate('//a[not(*) and not(text()[normalize-space()])]');
$i = $empty_anchors->length - 1; 
while ($i > -1) { 
    $element = $empty_anchors->item($i);  
    $element->parentNode->removeChild($element); 
    $i--; 
} 

echo $dom->saveHTML();

答案 1 :(得分:1)

您可以检查firstChild是否存在,只需将foreach循环更改为:

foreach($as as $a)
{
    if($a->firstChild === NULL && is_object($a))
    {
        #remove links without nodevalues
        $a->parentNode->removeChild($a);
    }
}
  

则firstChild

     

此节点的第一个子节点。如果没有这样的节点,则返回NULL