mehr-it/html-cleaner

HTML 清理器,用于从 HTML 片段中移除不需要的标签、属性和元素

1.1.0 2020-06-10 17:57 UTC

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' 有特殊含义,它将替换为解除包裹的节点的所有子节点。任何其他字符串都将转换为文本节点。