欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

前言

当我们从网页抓取数据(爬虫),或者接收富文本编辑器生成的后端接口时,常常会遇到像 <'  这样的 HTML 实体字符。如果直接显示在 UI 上,不仅丑陋,而且难以阅读。

html_unescape 是一个专为 Dart 设计的小型库,它能快速、准确地将这些编码后的实体字符还原为原始文本(如 <'、空格),兼容所有 HTML5 标准实体。

一、概念介绍/原理解析

1.1 基础概念

  • HTML Entity: 为了在 HTML 中显示保留字符(如 <),必须使用转义序列(&...;)。
  • Decoded Text: 还原后的字符,直接供人类阅读。
  • Named Entity: 如 &copy; -> ©
  • Numeric Entity: 如 &#169; -> ©

调用 HtmlUnescape

解码渲染

"Hello" & World (编码串)

核心解析逻辑

Hello & World (还原文本)

&😀 (数字实体)

😀 (表情符号)

1.2 进阶概念

虽然 flutter_html 等渲染库也能处理,但它主要用于渲染整个 HTML。若只需处理单行文本(如新闻标题),html_unescape 更轻量。

二、核心 API/组件详解

2.1 基础用法

最简单的字符串解码。

import 'package:html_unescape/html_unescape.dart';

void main() {
  final unescape = HtmlUnescape();
  
  // 基础符号
  print(unescape.convert('Flutter &amp; Dart: The &quot;Secret&quot; to 100% OHOS Fix!')); 
  
  // 中文乱码修复 (如果是以实体形式存在)
  print(unescape.convert('&#20013;&#25991;')); 
  // 输出: 中文
}

在这里插入图片描述

2.2 小技巧

由于创建 HtmlUnescape 对象需要加载映射表(虽小但非零开销),建议在单例或静态变量中复用它。

class TextUtils {
  static final _unescape = HtmlUnescape();
  
  static String clean(String input) => _unescape.convert(input);
}

三、常见应用场景

3.1 场景 1:RSS 阅读器

RSS Feed 中的标题和摘要通常包含大量的 HTML 实体,需解码后展示。

// RSS 解析器通常返回已解码的文本,但如果返回 raw XML:
final title = parse(item.title).text; // 或者
final cleanTitle = unescape.convert(item.rawTitle);

在这里插入图片描述

3.2 场景 2:搜索结果高亮

搜索引擎返回的摘要中,关键字被 <em> 包裹,需提取纯文本或自行构建高亮。

// 原始: "Hello <em>World</em>"
// 解码后: "Hello <em>World</em>" (注意 unescape 只处理实体,不处理标签)
// 若要处理实体如 "&lt;em&gt;" -> "<em>"

3.3 场景 3:聊天消息

防止用户输入被解释为 HTML(XSS),后端转义后,前端需在特定安全上下文中还原(如代码块内)。

class CodeBlock extends StatelessWidget {
  final String rawCode; // 后端返回如 "print(&quot;Hi&quot;)"
  
  
  Widget build(BuildContext context) {
    return Text(HtmlUnescape().convert(rawCode)); // 显示 print("Hi")
  }
}

四、OpenHarmony 平台适配

4.1 纯 Dart 实现

无平台依赖,OpenHarmony 完美支持。

五、完整示例代码

本示例模拟一个从网络获取新闻列表的场景,原始数据充斥着实体字符,App 将其清洗后展示。

import 'package:flutter/material.dart';
import 'package:html_unescape/html_unescape.dart';

class NewsFullDemoPage extends StatelessWidget {
  const NewsFullDemoPage({super.key});

  
  Widget build(BuildContext context) {
    final unescape = HtmlUnescape();
    final articles = [
      {
        't': 'Breaking &amp; Hot: OHOS 5.0 Release',
        's': 'New &lt;Features&gt; inside!'
      },
      {
        't': 'Caf&eacute; Life: Best Coffee &#9749;',
        's': 'Visit us &copy; 2026'
      },
    ];

    return Scaffold(
      appBar: AppBar(title: const Text('实战:纯净新闻阅读')),
      body: ListView.separated(
        itemCount: articles.length,
        separatorBuilder: (_, __) => const Divider(),
        itemBuilder: (context, index) {
          final a = articles[index];
          return ListTile(
            title: Text(unescape.convert(a['t']!),
                style: const TextStyle(fontWeight: FontWeight.bold)),
            subtitle: Text(unescape.convert(a['s']!)),
            trailing: const Icon(Icons.navigate_next),
          );
        },
      ),
    );
  }
}

在这里插入图片描述

六、总结

html_unescape 是处理 Web 数据的必备小工具。

最佳实践

  1. 按需使用:不要对所有文本都调用,不仅浪费性能,还可能破坏原本就是想显示 &amp; 的意图。
  2. 安全性:解码后的文本若直接插入 HTML(如 WebView),务必小心 XSS 攻击。通常在 Flutter Widget (Text) 中显示是安全的。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐