You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PostgreSQL中移除HTML标签并保留指定例外标签?

实现PostgreSQL版类似PHP strip_tags的标签过滤(保留指定标签)

1. 自定义strip_tags函数

先创建一个PL/pgSQL函数,通过"占位符替换"逻辑实现保留指定HTML标签、移除其余标签的效果——先保护允许的标签不被误删,再清除所有剩余标签,最后恢复允许的标签。

CREATE OR REPLACE FUNCTION strip_tags_keep_allowed(input_text text, allowed_tags text)
RETURNS text AS $$
DECLARE
    tag_pattern text;
    placeholder_prefix text := '__TAG_HOLDER__';
    placeholder_counter integer := 0;
    temp_text text := input_text;
    matched_tags text[];
    current_tag text;
BEGIN
    -- 自动为允许的标签添加对应的闭合标签(比如传入i会自动包含/i)
    allowed_tags := allowed_tags || ',' || replace(allowed_tags, ',', ',/');
    -- 构建匹配允许标签的正则(支持带属性的标签,比如<p class="demo">)
    tag_pattern := '<(' || replace(allowed_tags, ',', '|') || ')([^>]*)>';

    -- 第一步:将所有允许的标签替换为唯一占位符,避免被后续清除
    WHILE temp_text ~ tag_pattern LOOP
        current_tag := substring(temp_text FROM tag_pattern);
        temp_text := regexp_replace(temp_text, tag_pattern, placeholder_prefix || placeholder_counter, 'g');
        matched_tags[placeholder_counter] := current_tag;
        placeholder_counter := placeholder_counter + 1;
    END LOOP;

    -- 第二步:移除所有剩余的HTML标签
    temp_text := regexp_replace(temp_text, '<[^>]*>', '', 'g');

    -- 第三步:将占位符替换回原允许的标签
    FOR i IN 0..array_length(matched_tags, 1)-1 LOOP
        temp_text := replace(temp_text, placeholder_prefix || i, matched_tags[i]);
    END LOOP;

    RETURN temp_text;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

函数使用示例

-- 保留h1、p、strong、i标签,移除其他所有标签
SELECT strip_tags_keep_allowed(
    '<h1>测试标题</h1><p>这是<em>需要移除</em>的内容,<strong>加粗</strong>和<i>斜体</i>要保留,<script>alert("恶意脚本")</script>会被清除',
    'h1,p,strong,i'
);

执行后输出:

<h1>测试标题</h1><p>这是需要移除的内容,<strong>加粗</strong>和<i>斜体</i>要保留,会被清除

2. 用触发器自动处理字段

如果需要在插入/更新数据时自动清洗内容,可以创建触发器绑定上述函数。

假设你的表是content,包含raw_content(存储富文本原始内容)和clean_content(存储清洗后的内容)字段:

第一步:创建触发器函数

CREATE OR REPLACE FUNCTION clean_content_trigger()
RETURNS TRIGGER AS $$
BEGIN
    -- 指定允许保留的标签,按需修改
    NEW.clean_content := strip_tags_keep_allowed(NEW.raw_content, 'h1,p,strong,i');
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

第二步:创建触发器

CREATE TRIGGER trigger_auto_clean_content
BEFORE INSERT OR UPDATE ON content
FOR EACH ROW EXECUTE FUNCTION clean_content_trigger();

之后每次插入或更新raw_content时,clean_content会自动生成清洗后的内容。

注意事项

  • 该函数支持带属性的允许标签(比如<p class="article">会被完整保留),如果需要仅保留无属性的标签,可以将正则修改为:
    tag_pattern := '<(' || replace(allowed_tags, ',', '|') || ')\s*>|<(' || replace(allowed_tags, ',', '|') || ')>';
    
  • 正则处理HTML存在局限性,对于嵌套过深、不规范的HTML(比如未闭合标签)可能出现异常。如果需要更严谨的HTML解析,可以结合PostgreSQL的xml类型进行处理(复杂度更高)。
  • 函数标记为IMMUTABLE,意味着相同输入会返回相同输出,适合用于索引或缓存优化。

内容的提问来源于stack exchange,提问作者Blumenthaler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 12:30:41