正则表达式匹配HTML标记不包含其他标记

时间:2010-08-18 15:51:21

标签: php html regex dom

我正在编写一个正则表达式查找/替换,它将<span>插入到<a href>尚不存在的文件中的每个<span>。它允许其他代码位于<a href>,如<img><b>等。

目前我有这个正则表达式:
查找:(<a[^>]+?style=".*?color:#(\w{6}).*?".*?>)(.+?)(<\/a>)
替换:'$1<span style="color:#$2;">$3</span>$4'

它的效果很好,除非我在同一个文件上运行它,它会在<span>内部插入<span>并且它会变得混乱。

目标示例:

我们希望它忽略这一点:
    <a href="http://mywebiste.com/link1.html" target="_blank" style="color:#bfbcba; text-decoration:underline;"><span style="color:#bfbcba;">Howdy</span></a>

但不是这样:
    <a href="http://mywebiste.com/link1.html" target="_blank" style="color:#bfbcba; text-decoration:underline;">Howdy</a>

或者这个:
    <a href="http://mywebiste.com/link1.html" target="_blank" style="color:#bfbcba; text-decoration:underline;"><img src="myimg.gif" />Howdy</a>

- 编辑 -

根据评论中的建议使用PHP DOM库,这是我到目前为止所做的:

$doc = new DOMDocument();
$doc->loadHTML($input);
$tags = $doc->getElementsByTagName('a');
foreach ($tags as $tag) {
    $spancount = $tag->getElementsByTagName("span")->length;
    if($spancount == 0){
        $element = $doc->createElement('span');
        $tag->appendChild($element);
    }
}

echo $doc->saveHTML();`

目前它会检测锚内是否有跨度,如果有,它会在锚的内部追加一个跨度,但是,我还没弄明白如何在里面找到锚的原始内容跨度。

1 个答案:

答案 0 :(得分:4)

不要使用正则表达式,它不适合HTML。

使用DOM库和getElementsByTagName('a')然后使用getElementsByTagName('span')属性遍历每个锚点并查看它是否包含length的子span元素。如果没有,请appendChild或将锚节点的firstChild分配给使用document.createElement('span')创建的新范围。

编辑:至于抓取锚点的内部html,如果里面有很多节点,请尝试使用:

<?php
function innerHTML($node){
  $doc = new DOMDocument();
  foreach ($node->childNodes as $child)
    $doc->appendChild($doc->importNode($child, true));

  return $doc->saveHTML();
}

$html = innerHTML( $anchorRef );

这也可以帮助您:Change innerHTML of a php DOMElement