如何使用C++标准库对XML字符串进行反转义处理?
解决XML字符串反转义的问题
嘿,我来帮你搞定这个XML反转义的实现!首先先提个小问题:你现在的escape_XML函数里有几个语法错误——比如你用了chr == '"'这种写法,但chr是单个char类型,双引号应该直接写'"'或者\",单引号是'\'',&就是'&',这些是字符字面量,不是字符串转义哦。先把这个修正了,再来看反转义的实现。
对于unescape_XML,确实不能用简单的逐个字符遍历,因为转义序列是多字符的(比如&是5个字符)。我们可以用索引遍历,遇到&的时候就尝试匹配后续的转义序列,具体思路如下:
- 用一个索引变量遍历输入字符串,而非范围for循环
- 当遇到
&时,查找后面最近的;,截取中间的标识部分(比如"中间的quot) - 根据标识匹配对应的原始字符,匹配成功就跳过整个转义序列,失败就保留
&继续遍历 - 非
&的字符直接添加到输出
下面是修正后的完整代码:
#include <iostream> #include <string> std::string escape_XML(const std::string &input) { std::string output; output.reserve(input.size()); // 预分配空间提升性能 for (char chr : input) { switch(chr) { case '"': output += """; break; case '&': output += "&"; break; case '<': output += "<"; break; case '>': output += ">"; break; case '\'': output += "'"; break; default: output += chr; break; } } return output; } std::string unescape_XML(const std::string &input) { std::string output; output.reserve(input.size()); // 预分配空间 const size_t len = input.size(); size_t i = 0; while (i < len) { if (input[i] == '&') { // 查找当前&后面的第一个; size_t semicolon_pos = input.find(';', i); if (semicolon_pos != std::string::npos && semicolon_pos > i + 1) { // 截取&和;之间的部分 std::string entity = input.substr(i + 1, semicolon_pos - i - 1); // 匹配转义实体 if (entity == "quot") { output += '"'; i = semicolon_pos + 1; // 跳过整个转义序列 continue; } else if (entity == "amp") { output += '&'; i = semicolon_pos + 1; continue; } else if (entity == "lt") { output += '<'; i = semicolon_pos + 1; continue; } else if (entity == "gt") { output += '>'; i = semicolon_pos + 1; continue; } else if (entity == "apos") { output += '\''; i = semicolon_pos + 1; continue; } } // 如果没匹配到有效实体,就保留&,继续遍历 output += input[i]; ++i; } else { // 普通字符直接添加 output += input[i]; ++i; } } return output; } int main() { std::string input{ "\" <-> "\n" "& <-> &\n" "< <-> <\n" "> <-> >\n" "' <-> '\n" }; const std::string escaped = escape_XML(input); std::cout << "ESCAPED" << std::endl; std::cout << escaped; const std::string unescaped = unescape_XML(escaped); std::cout << "UNESCAPED" << std::endl; std::cout << unescaped; std::cout << std::flush; }
代码说明:
- 修正后的escape_XML:用switch替代多个if-else更简洁,同时添加了
reserve预分配输出空间,避免频繁内存分配提升性能。 - unescape_XML:
- 用索引遍历,遇到
&时查找后续的;,截取中间的实体名称 - 匹配到有效实体就替换为对应字符,并跳过整个转义序列
- 对于无效的实体(比如
&abc;或者末尾没;的&),直接保留原始字符,避免破坏输入
- 用索引遍历,遇到
- main函数:修正了字符串字面量的写法,确保测试用例正确。
这个实现完全基于C++标准库,没有依赖第三方工具,而且能处理各种边界情况,比如无效转义序列、字符串末尾的&等。
内容的提问来源于stack exchange,提问作者dumbo
相关产品推荐
相关产品推荐

