将 <img> 元素包装在 <div> 中,但允许 <a> 标签

Wrap <img> elements in <div> but allow for <a> tags

我有一个函数可以使用 DOMDocument 扫描字符串中的 img 标签并将它们包装在 div 中。

    $str = 'string containing HTML';
    $doc = new DOMDocument();
    $doc->loadHtml(mb_convert_encoding($str, 'HTML-ENTITIES', 'UTF-8'));

    $tags = $doc->getElementsByTagName('img');

    foreach ($tags as $tag) {
        $div = $doc->createElement('div');
        $tag->parentNode->insertBefore($div, $tag);
        $div->appendChild($tag);
    }

    return $str;

但是,当 img 包含在 a 标签中时,a 标签将被移除,并且 'replaced' 包含 div。如何保留 a 标签?

目前,

<a href="http://google.com"><img src="srctoimg"/></a>

结果;

<div><img src="srctoimg"/></div>

而不是;

<div><a href="http://google.com"><img src="srctoimg"/></a></div>

是否有 'wildcard' 我可以将第二个参数传递给 insertBefore() 或者我该如何实现?

使用 if 子句可能是最简单的:

foreach ($tags as $tag) {
    $div = $doc->createElement('div');
    $x = $tag->parentNode;

    // Parent node is not 'a': insert before <img>
    if($tag->parentNode->tag != 'a') {
      $tag->parentNode->insertBefore($div, $tag);
    }
    // Parent node is 'a': insert before <a>
    else{
      $tag->parentNode->parentNode->insertBefore($div, $tag);
    }

    $div->appendChild($tag);
}

在你的 foreach 中尝试这个

$parent = $tag->parentNode;
if( $parent->tagName == 'a' )
{
    $parent->parentNode->insertBefore($div, $parent);
    $div->appendChild($parent);
}
else
{
    $tag->parentNode->insertBefore($div, $tag);
    $div->appendChild($tag);
}

您可以使用 XPath 查询来完成此操作。

'//*[img/parent::a or (self::img and not(parent::a))]'

这将为具有 a 父级的任何 img 标签以及任何 image 标签本身获取 父级 对于没有直接 a 父级的任何 img 标签。

这样您就不必更改循环中的代码。

$str = <<<EOS
<html>
<body>
    Image with link:
    <a href="http://google.com">
        <img src="srctoimg"/>
    </a>

    Image without link:
    <img src="srctoimg"/>
</body>
</html>
EOS;

$doc = new DOMDocument();
$doc->loadHtml(mb_convert_encoding($str, 'HTML-ENTITIES', 'UTF-8'));

$xpath = new DOMXPath($doc);
$tags  = $xpath->query(
    '//*[img/parent::a or (self::img and not(parent::a))]'
);

foreach ($tags as $tag) {
    $div = $doc->createElement('div');
    $tag->parentNode->insertBefore($div, $tag);
    $div->appendChild($tag);
}

echo $doc->saveHTML();

输出(为清楚起见缩进):

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<body>
    Image with link:
    <div>
        <a href="http://google.com">
            <img src="srctoimg">
        </a>
    </div>

    Image without link:
    <div>
        <img src="srctoimg">
    </div>
</body>
</html>

使用 xpath

$str = 'string containing HTML';
        $doc = new DOMDocument();
        $doc->loadHtml(mb_convert_encoding($str, 'HTML-ENTITIES', 'UTF-8'));
        $xpath = new DOMXPath($doc);

        $tags0 = $xpath->query('//a/img'); // get all <img> in <a> tag
        $tags1 = $xpath->query('//img[not(parent::a)]'); // get all <img> except those with parent <a> tag
        $tags = array_merge($tags0,$tags1); // merge the 2 arrays
        foreach ($tags as $tag) {
            $div = $doc->createElement('div');
            $tag->parentNode->insertBefore($div, $tag);
            $div->appendChild($tag);
        }

        return $str;

您好,我使用 jquery 提供此解决方案。我知道你在 php.

中问过这个问题
<a href="http://google.com"><img src="srctoimg"/></a>
<script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
  <script>
 $('a').replaceWith(function(){
    return $('<div/>', {
        html: this.innerHTML
    })
})
</script>