如何使用boost::property_tree生成无缩进但带换行的XML?
Boost Property Tree XML 格式化:无缩进但带换行的实现
我太懂这种需求了——用Boost Property Tree写XML时,默认的格式化逻辑总是有点“轴”:要么缩进加换行整整齐齐,要么把所有内容挤成一行。你用的Boost 1.66版本里,xml_writer_settings把indent_count设为0时,确实会连换行都给你去掉,完全不符合预期。
不用事后去修改文件,咱们直接自定义一个XML writer就能搞定,完美实现你要的“无缩进但带换行”的格式。
具体实现方案
Boost Property Tree允许我们传入自定义的元素写入函数,来控制每个XML节点的输出逻辑。我们只需要重写元素节点的输出规则:在根节点的开始标签后加换行,每个子节点单独占一行,最后根节点的闭合标签也单独换行,同时完全去掉缩进空格。
下面是完整的可运行代码:
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> #include <iostream> using namespace boost::property_tree; // 自定义XML元素写入逻辑 template<typename Ptree> void custom_xml_element_writer(const std::string& key, const Ptree& pt, std::basic_ostream<typename Ptree::key_type::value_type>& stream, const xml_writer_settings<typename Ptree::key_type>& settings) { // 输出元素开始标签 stream << settings.tab << '<' << key; // 处理元素属性(如果存在) for (const auto& attr : pt.get_child("<xmlattr>", Ptree())) { stream << ' ' << attr.first << "=\"" << attr.second.get_value<std::string>() << '"'; } if (pt.empty()) { // 空元素直接闭合 stream << "/>" << settings.newline; } else { // 非空元素:开始标签后换行,输出子节点,最后闭合标签换行 stream << '>' << settings.newline; // 遍历输出所有子节点(跳过属性节点) for (const auto& child : pt) { if (child.first != "<xmlattr>") { write_xml_element(stream, child.first, child.second, settings); } } // 输出闭合标签 stream << settings.tab << "</" << key << '>' << settings.newline; } } int main() { ptree tree; ptree* root = &tree.add("root", ""); root->add("something", "yes"); root->add("something2", "no"); // 配置:换行符用'\n',缩进数为0(无缩进空格) xml_writer_settings<ptree::key_type> writer_settings('\n', 0); // 调用带自定义writer的write_xml write_xml("test.xml", tree, std::locale(), writer_settings, &custom_xml_element_writer<ptree>); return 0; }
代码逻辑说明
- 自定义的
custom_xml_element_writer函数是核心:它会在非空元素的开始标签后强制添加换行,然后逐个输出子节点(每个子节点都会触发同样的换行逻辑),最后在闭合标签前也添加换行。 - 因为我们设置
indent_count=0,settings.tab会是空字符串,所以不会产生任何缩进空格,完全符合你“无缩进字符”的要求。 - 调用
write_xml时,最后一个参数传入我们的自定义writer函数,覆盖默认的输出逻辑。
最终生成的XML效果
运行这段代码后,生成的test.xml内容会是:
<?xml version="1.0" encoding="utf-8"?> <root> <something>yes</something> <something2>no</something2> </root>
如果你的实际需求是子节点前面需要一个空格(就像你示例里那样),只需要把writer_settings的缩进数改成1,缩进字符设为空格即可:
xml_writer_settings<ptree::key_type> writer_settings('\n', 1, ' ');
这样生成的XML就会和你给出的示例完全一致了。
内容的提问来源于stack exchange,提问作者JAJA
相关产品推荐
相关产品推荐

