mehr-it / html-cleaner
HTML 清理器,用于从 HTML 片段中移除不需要的标签、属性和元素
Requires
- php: >=7.1.0
- ext-dom: *
- masterminds/html5: ^2.0
Requires (Dev)
- phpunit/phpunit: ^7.4
This package is auto-updated.
Last update: 2024-09-10 17:33:19 UTC
README
此库旨在提供一个简单的 API,用于从给定的 HTML 片段中移除不需要的元素。当从不受信任的源输出 HTML,例如浏览器、API 客户端或其他第三方时,这是必需的。
用法
HtmlCleaner
类允许定义元素类型、标签名称和属性的黑白名单。如果需要更多定制,可以定义回调进行过滤。
限制允许的标签
以下示例仅允许 <p>
和 <br>
标签。所有其他标签及其内容都将被移除。
$cleaned = (new HtmlCleaner())
->setTagWhitelist(['p', 'br'])
->cleanFragment($html);
可以使用 setTagBlacklist()
通过黑名单进行限制,或者甚至可以定义一个回调,该回调接收标签名称并必须返回 true
以保留指定的标签
$cleaned = (new HtmlCleaner())
->setTagCallback(function($tag, $cleaner) {
return $tag == 'span';
})
->cleanFragment($html);
限制元素类型
HTML 还包含其他元素,例如注释和 CDATA。它们不能通过标签名称进行过滤,但可以使用与标签限制相同的方式使用元素过滤器函数。以下示例仅允许标签和文本节点
$cleaned = (new HtmlCleaner())
->setElementTypeWhitelist([
HtmlCleaner::ELEMENT_TYPE_TAG,
HtmlCleaner::ELEMENT_TYPE_TEXT,
])
->cleanFragment($html);
过滤属性
即使某些标签应该被允许,某些属性可能需要被移除。以下示例仅允许 style
属性
$cleaned = (new HtmlCleaner())
->setAttributeWhitelist(['style'])
->cleanFragment($html);
如果应该移除所有属性,可以使用带有通配符条目 '*'
的黑名单
$cleaned = (new HtmlCleaner())
->setAttributeBlacklist(['*'])
->cleanFragment($html);
替换节点
想象以下 HTML 片段
<p>A big search engine is called <a href="https://www.google.com">Google</a>.</p>
简单地移除所有 <a>
标签,也会导致其内容被移除。但如果文本应该保留呢?这里就是替换功能的作用所在。以下示例将所有 <a>
标签替换为 <span>
$cleaned = (new HtmlCleaner())
->setReplacements([
'a' => 'span'
])
->cleanFragment($html);
// output: "<p>A big search engine is called <span>Google</span>.</p>"
如您所见,现有的属性将自动移除。
要移除 <span>
标签,您只需将值传递为 null
,以仅保留节点的文本内容
$cleaned = (new HtmlCleaner())
->setReplacements([
'a' => null
])
->cleanFragment($html);
// output: "<p>A big search engine is called Google.</p>"
您甚至可以传递一个 Closure
作为替换,以生成替换值,例如标签名称、null
或甚至新创建的 DOMNode
。如果回调返回 false
,则对应的节点不会被替换,而是被移除。
解除节点包裹
有时替换节点不是您想要的。通常,您可能想要移除某些节点,但保留其内容。您可以使用“解除包裹”列表指定这些节点
$html = '<p>This is <b>me</b> and you</p>
$cleaned = (new HtmlCleaner())
->setUnwraps([
'p',
])
->cleanFragment($html);
// output: "This is <b>me</b> and you"
您可以将 '*'
作为通配符传递以解除任何节点的包裹。注意:**替换具有优先级高于解除包裹**!
如果您想要解除一个节点并预置/附加其他元素,可以传递一个关联数组
$html = '<p>This is <b>me</b> and you</p>
$cleaned = (new HtmlCleaner())
->setUnwraps([
'p',
'b' => ['about ', ':innerHtml', ', my life'],
])
->cleanFragment($html);
// output: "This is about me, my life and you"
字符串 ':innerHTML'
有特殊含义,它将替换为解除包裹的节点的所有子节点。任何其他字符串都将转换为文本节点。