正则表达式:仅当html标记包含特定的类ID时才匹配

时间:2010-07-30 04:52:32

标签: php regex

在php中使用perl regex匹配html标记。

如果标记在开放标记中的某处包含“class = details”,则希望标记匹配。

希望匹配<table border="0" class="details">而不是<table border="0">

写这个以匹配它:

'#<table(.+?)class="details"(.+?)>#is'

<table(.+?)会产生一个问题,因为它匹配的第一个表标记只有在找到class="details"时才会停止匹配,无论代码发生多远。

我认为这个逻辑可以解决我的问题:

“匹配<table但仅在下一个class="details"之前包含>

我怎么写这个?

4 个答案:

答案 0 :(得分:3)

虽然正则表达式可以适用于各种各样的任务,但我发现解析HTML DOM时通常会遇到这种情况。 HTML的问题在于,文档的结构变化很大,难以准确(并且准确地说,我的意思是100%的成功率,没有误报)提取标签。

我建议您使用DOM解析器,例如phpQuery,并将其用作以下内容:

function get_first_image($html){
    $dom = phpQuery::newDocument($html);

    $first_img = $dom->find('img:first');

    if($first_img !== null) {
        return $first_img->attr('src');
    }

    return null;
}

有些人可能认为这样做有点过分,但最终,维护起来会更容易,并且还可以提供更多的可扩展性。例如,使用DOM解析器,我也可以获得alt属性。

可以设计一个正则表达式来实现相同的目标但是会限制它会强制alt属性位于src之后或相反的​​目标,并克服此限制会增加正则表达式的复杂性。

另外,请考虑以下内容。要使用正则表达式正确匹配<img>标记并仅获取src属性(在第2组中捕获),您需要以下正则表达式:

<\s*?img\s+[^>]*?\s*src\s*=\s*(["'])((\\?+.)*?)\1[^>]*?>

然后,如果出现以上情况,则上述情况可能会失败:

  • 属性或标记名称为大写,并且不使用 i 修饰符。
  • src属性周围没有使用引号。
  • 然后src的另一个属性在其值的某处使用>字符。
  • 我没有预料到的其他一些原因。

所以再一次,不要使用正则表达式来解析dom文档。

有关如何使用phpQuery解决问题的简单示例:

$dom = phpQuery::newDocument($html);
$matching_tags = $dom->find('.details');

答案 1 :(得分:1)

你可能需要在某种形式上保持积极的态度,作为一种非常粗略的形式,显然有其局限性......

<table(?=[^>]*class="details")[^>]*>

答案 2 :(得分:1)

HTML使用正则表达式无法解析(可靠)。很少有简单的案例有解决方案,但它们是例外。我认为你的案例使用正则表达式无法解决,但我不确定

您应该使用XML工具和XPath等XML解析器来搜索和测试您的条件。编写与您的案例相匹配的表达式非常简单。我不知道如何在PHP中构建XML树并执行XPath查询,但XPath表达式是

//table[@class='details']

答案 3 :(得分:0)

您可以使用如下所示的正则表达式:

<\/?table[^>]*(class="details")*>

但上述用户说使用xml / html类型解析器找到你的项目要好得多。