html实体是浏览器解析时才还原的编码,如&、

什么是HTML实体,为什么不能直接用std::string替换
HTML实体(如 &、、<code>"、>)不是普通字符,而是浏览器解析时才还原的编码。C++标准库不提供内置解码函数,硬写字符串替换容易漏掉命名实体(如 )、十进制/十六进制数字实体( 、 ),或误替换嵌套内容(比如 & 应解为 &,而非两次替换成 &)。
手动解码需覆盖三类实体:命名、十进制、十六进制
解码逻辑必须按优先级顺序处理:先处理数字实体(避免被命名实体规则干扰),再处理命名实体。否则 可能被误当作 <code>& + #60; 处理。
→ <code>(十进制,<code>开头,分号结尾)→ <code>(十六进制,<code>开头,不区分大小写,分号结尾)→ <code>(命名,查表匹配,注意 <code>&必须最后处理,否则会破坏其他实体)
示例片段:
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
std::string html_decode(const std::string& s) {
std::string out;
size_t i = 0;
while (i = 0 && code (code);
else if (code (0xC0 | (code >> 6));
out += static_cast<char>(0x80 | (code & 0x3F));
} else {
out += static_cast<char>(0xE0 | (code >> 12));
out += static_cast<char>(0x80 | ((code >> 6) & 0x3F));
out += static_cast<char>(0x80 | (code & 0x3F));
}
i = end + 1;
continue;
}
} else {
// 命名实体,查表(简化版只列常见几个)
static const std::unordered_map<:string char> named = {
{"lt", ''}, {"amp", '&'}, {"quot", '"'}, {"apos", '\''}
};
auto it = named.find(ent);
if (it != named.end()) {
out += it->second;
i = end + 1;
continue;
}
}
}
}
out += s[i++];
}
return out;
}</:string></char></char></char></char>
用第三方库(如 htmlcxx 或 Boost.StringAlgo)反而更麻烦
htmlcxx 主要用于 HTML 解析,不提供轻量解码接口;Boost.StringAlgo 没有实体解码功能。真正可用的是 libxml2 的 htmlEntityLookup + 手动解析,但引入整个 XML 库只为解码太重。更现实的选择是:若项目已用 fmt 或 abseil,可自行补一个精简查表+数字解析函数;若只是偶尔解码,直接抄上面那段并补充所需命名实体(如 nbspc、copy)更可控。
边界情况和易错点
实际使用中最常踩坑的不是逻辑,而是细节:
- 未处理
&→ 必须确保&是最后一个解码的命名实体,否则<会先被替成,再被当成新实体二次解析 - 十六进制实体忽略大小写:
和都合法,std::stoi(..., nullptr, 16)能自动处理 - 分号缺失时不应解码:
<不是有效实体,应原样保留 - UTF-8 输出需兼容非 ASCII 字符:上面示例只处理 BMP(U+0000–U+FFFF),若输入含 emoji(如
😂→ U+1F602),需支持四字节 UTF-8 编码
真正在生产环境用,建议把命名实体表做成 std::map 或 std::unordered_map,并加单元测试覆盖 、 、 、& 这四类典型组合。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










