【问题标题】:RegEx to extract all HTML tag attributes including inline JavaScript正则表达式提取所有 HTML 标记属性,包括内联 JavaScript
【发布时间】:2011-01-24 22:07:36
【问题描述】:

我在寻找解析 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 sn-ps。如果有更好、更轻量级的方法来实现这一点,我愿意接受建议。

【问题讨论】:

  • 不要用正则表达式解析html... -_-
  • 这就是为什么你不应该用正则表达式解析 html。
  • 所以,title="Hello 'cruel' World" 也不起作用。

标签: html regex tags


【解决方案1】:

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

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

【讨论】:

  • 关闭,但 HTML 4.01 属性值可以包含尖括号。此外,属性名称和未加引号的属性值可能包含破折号、点和冒号。因此,更好的表达方式是:([\w\-.:]+)\s*=\s*("[^"]*"|'[^']*'|[\w\-.:]+)(迂腐,我知道...)
  • 好吧,这不适用于有 a="b+c" 周围没有标签的文本,也许试试:(&lt;\w.)([\w\-.:]+)\s*=\s*("[^"]*"|'[^']*'|[\w\-.:]+)
【解决方案2】:

以下正则表达式将按照此处提供的 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);

希望这会有所帮助。

【讨论】:

    【解决方案3】:

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

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

    其中\\2 是对(["']) 的引用

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

    【讨论】:

    • 怎么样:"attrib_name = unquoted_value"?
    • 属性/值定义中的空格——据我所知——是不允许的。或者这不是你要问的吗?
    • 抱歉不清楚。您的解决方案将属性与被引用的值(name="dq val"name='sq val')匹配,但无法将属性与 未引用 值匹配(name=uq_val
    • 是的,我知道这一点,并且我在回答中也提到了这一点;)不过,根据 W3 xhtml 规范,必须始终引用属性值。 (w3.org/TR/xhtml1/#h-4.4) 现在有了 html5 和充满对象的数据属性,引用几乎是必要的。
    • Koen,属性、= 符号和属性值之间的额外空格是允许的。另外,我看不出 XHTML 与 2013 年有什么关系。在 HTML 中,属性值周围的引号是可选的(通常),但根据您要使用的属性值,您仍然会时不时地需要它们。请参阅Unquoted attribute values in HTML, CSS and JavaScript 了解更多信息。
    猜你喜欢
    • 2011-10-07
    • 2020-11-07
    • 1970-01-01
    • 2013-09-05
    • 2012-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多