本文介绍为何不应使用正则表达式处理 HTML,并提供基于 DOM 解析的专业方案,通过 DOMParser 或临时 DOM 节点清除 、、、 等标签内部的文本内容,确保结构安全、语义准确、无副作用。
本文介绍为何不应使用正则表达式处理 html,并提供基于 dom 解析的专业方案,通过 `domparser` 或临时 dom 节点清除 ``、``、``、`` 等标签内部的文本内容,确保结构安全、语义准确、无副作用。
在 Web 开发中,一个常见误区是试图用正则表达式(regex)从 HTML 字符串中“提取链接”或“过滤文本”,同时排除特定标签(如 、)内部的内容。然而,HTML 是上下文敏感的嵌套结构,而正则表达式本质上不具备解析嵌套语法的能力。您提供的复杂正则虽能匹配 URL,但无法可靠判断某段文本是否位于 的属性值中、 的起始与结束标签之间,或是被注释、CDATA、JS 字符串等上下文包裹——这极易导致误匹配、截断或 XSS 风险。
✅ 正确做法:交由浏览器原生 HTML 解析器处理
现代浏览器提供了健壮、标准兼容的 DOM 解析能力。我们应利用 DOMParser(推荐)或临时 document.createElement('div'),将 HTML 字符串安全转换为 DOM 树,再精准定位并清空目标标签的子内容(保留标签本身),最后序列化回 HTML 字符串。
✅ 推荐方案:使用 DOMParser(无副作用、无需操作真实 DOM)
function sanitizeTags(html, tagsToEmpty = ['figure', 'img', 'picture', 'trix-attachment']) {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
tagsToEmpty.forEach(tagName => {
const elements = doc.querySelectorAll(tagName);
elements.forEach(el => {
// 清空所有子节点,仅保留空标签(如 @@##@@ → @@##@@,<figure> → <figure></figure>)
el.replaceWith(doc.createElement(tagName));
});
});
// 注意:parseFromString 生成的文档无 <body> 时,doc.body 可能为 null;
// 安全写法:取 body 内容,若无则取整个 documentElement
return doc.body?.innerHTML || doc.documentElement?.innerHTML || '';
}
// 使用示例
const input = 'Check this: https://example.com. Here is a figure: <figure>@@##@@<p>Remove me!</p></figure>. And an image: @@##@@Keep this link: https://safe.org';
const result = sanitizeTags(input, ['figure', 'img']);
console.log(result);
// 输出:Check this: https://example.com. Here is a figure: <figure></figure>. And an image: @@##@@.Keep this link: https://safe.org