首页 > 解决方案 > 使用 boost::property_tree 编写 CDATA XML 节点

问题描述

我正在尝试使用 boost::property_tree 编写一个包含 CDATA 节点的 XML 文件。但是,由于诸如<, >,&等字符在编写 XML 文件时会自动转义,例如

xml.put("node", "<![CDATA[message]]>")

将显示为

<node>&lt![CDATA[message]]&gt</node> 

在 XML 文件中。有没有办法使用 property_tree 正确编写 CDATA 节点,或者这仅仅是库的限制?

标签: c++xmlboostcdataboost-propertytree

解决方案


Boost 文档清楚地表明它无法区分 CDATA 和非 CDATA 值:

XML 存储编码不能完美地往返。读写周期会丢失修剪后的空白、低级格式化信息以及普通数据和 CDATA 节点之间的区别。评论仅在启用时保留。一个写-读周期丢失了修整的空白;也就是说,如果源树具有以空格开头或结尾的字符串数据,则该空格将丢失。

我遇到同样问题的几次都是针对非常特殊的情况,我知道不需要其他转义数据,因此对生成的文件进行简单的后处理替换转义字符就足够了。

作为一般示例:

std::ostringstream ss;
pt::write_xml(ss, xml, pt::xml_writer_make_settings<std::string>('\t', 1));

auto cleaned_xml = boost::replace_all_copy(ss.str(), "&gt;", ">");
cleaned_xml = boost::replace_all_copy(cleaned_xml, "&lt;", "<");
cleaned_xml = boost::replace_all_copy(cleaned_xml, "&amp;", "&"); // last one

std::ofstream fo(path);
fo << cleaned_xml;

更详细的解决方案应包括找到开头&lt;![CDATA[和结尾]]&gt,并仅在这些限制内替换以避免替换正确转义的符号。

这个答案中提出了另一种解决方案,但我从未使用过它。


推荐阅读