RegEx提取所有HTML标记属性,包括内联JavaScript

时间:2010-03-08 10:04:42

标签: html regex tags

我在寻找解析HTML标记属性时发现了这个有用的正则表达式代码:

(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?

效果很好,但缺少一个我需要的关键元素。一些属性是事件触发器,其中包含内联Javascript代码,如下所示:

onclick="doSomething(this, 'foo', 'bar');return false;"

或者:

onclick='doSomething(this, "foo", "bar");return false;'

我无法弄清楚当原始表达式嵌入包含属性值的引号集内时,如何使原始表达式不计算来自JS(单引号或双引号)的引号。

我应该补充说,这不是用于解析整个HTML文档。它在我更新的旧“数组选择菜单”功能中用作参数。其中一个参数是一个标签,可以将额外的HTML属性附加到表单元素。

我已经改进了函数并且不赞成旧的...但是如果代码中的某个地方是对旧函数的调用,我需要它将它们解析成新的数组格式。例如:

// Old Function
function create_form_element($array, $type, $selected="", $append_att="") { ... }
// Old Call
create_form_element($array, SELECT, $selected_value, "onchange=\"something(this, '444');\"");

新版本采用attr =>数组值对创建额外的标签。

create_select($array, $selected_value, array('style' => 'width:250px;', 'onchange' => "doSomething('foo', 'bar')"));

这只是一个向后兼容性问题,所有对OLD函数的调用都被路由到新函数,但是旧函数中的$ append_att参数需要被创建为新函数的数组,因此我需要使用正则表达式解析小HTML片段。如果有更好,更轻量级的方法来实现这一目标,我愿意接受建议。

3 个答案:

答案 0 :(得分:2)

正则表达式的问题在于它尝试同时处理单引号和双引号。它不支持包含其他引用的属性值。这个正则表达式会更好用:

(\w+)=("[^<>"]*"|'[^<>']*'|\w+)

答案 1 :(得分:1)

以下正则表达式将按照此处提供的HTML语法规范工作

http://www.w3.org/TR/html-markup/syntax.html

正则表达式

// valid tag names
$tagname = '[0-9a-zA-Z]+';
// valid attribute names
$attr = "[^\s\\x00\"'>/=\pC]+";
// valid unquoted attribute values
$uqval = "[^\s\"'=><`]*";
// valid single-quoted attribute values
$sqval = "[^'\\x00\pC]*";
// valid double-quoted attribute values
$dqval = "[^\"\\x00\pC]*";
// valid attribute-value pairs
$attrval = "(?:\s+$attr\s*=\s*\"$dqval\")|(?:\s+$attr\s*=\s*'$sqval')|(?:\s+$attr\s*=\s*$uqval)|(?:\s+$attr)"; 

,最终的正则表达式查询将是

    // start tags + all attr formats
    $patt[] = "<(?'starttags'$tagname)(?'tagattrs'($attrval)*)\s*(?'voidtags'[/]?)>";

    // end tags
    $patt[] = "</(?'endtags'$tagname)\s*>"; // end tag

    // full regex pcre pattern
    $patt = implode("|", $patt);
    // search and match
    preg_match_all("#$patt#imuUs",$data,$matches);

希望这会有所帮助。

答案 2 :(得分:0)

更好的方法是使用反向引用,在PHP中,正则表达式为:

([a-zA-Z_:][-a-zA-Z0-9_:.]+)=(["'])(.*?)\\2

\\2是对(["'])

的引用

此正则表达式也会匹配包含_-:的属性,这些属性是根据W3C允许的,但是,此表达式不会匹配引号中未包含的值的属性