使用yaml-cpp按路径遍历节点修改YAML文件值异常问题
yaml-cpp修改指定路径节点后输出异常的问题解决
在使用yaml-cpp加载并修改YAML文件时,通过路径遍历节点后修改值,最终输出的YAML结构丢失了原有的层级,不符合预期。
问题原因
yaml-cpp中的YAML::Node是值类型,赋值操作会创建节点的副本而非引用。你的遍历逻辑中,每次执行traverse = traverse[path_element]都会生成一个新的Node副本,最终traverse变成了脱离原root树的独立节点。修改这个副本的子元素不会影响原root树,且yaml-cpp的Emitter会错误地优先输出这个独立副本的内容,导致原root的层级结构丢失。
解决方案
要保持对原root树节点的引用,有两种常用方式:
方式1:使用指针遍历节点
通过指针直接操作原树中的节点,避免值拷贝:
#include <yaml-cpp/yaml.h> #include <iostream> #include <list> int main() { const std::string test_yaml = "node1:\n" " node2:\n" " node3:\n" " name: \"somevalue\""; YAML::Node root = YAML::Load(test_yaml); std::list<std::string> path; path.push_back("node1"); path.push_back("node2"); path.push_back("node3"); YAML::Node* traverse = &root; for (const std::string &path_element: path) { traverse = &((*traverse)[path_element]); } (*traverse)["name"] = "something else"; YAML::Emitter e; e << root; std::cout << e.c_str() << std::endl; return 0; }
方式2:遍历到倒数第二个节点,直接操作目标节点
只遍历到路径的倒数第二个节点,然后直接修改目标节点的子元素:
#include <yaml-cpp/yaml.h> #include <iostream> #include <list> int main() { const std::string test_yaml = "node1:\n" " node2:\n" " node3:\n" " name: \"somevalue\""; YAML::Node root = YAML::Load(test_yaml); std::list<std::string> path; path.push_back("node1"); path.push_back("node2"); path.push_back("node3"); YAML::Node traverse = root; auto path_it = path.begin(); // 遍历到倒数第一个元素之前 for (; std::next(path_it) != path.end(); ++path_it) { traverse = traverse[*path_it]; } // 修改目标节点的子元素 traverse[*path_it]["name"] = "something else"; YAML::Emitter e; e << root; std::cout << e.c_str() << std::endl; return 0; }
验证结果
编译运行修改后的代码,输出将符合预期:
node1: node2: node3: name: something else
内容的提问来源于stack exchange,提问作者Nidhoegger
相关产品推荐
相关产品推荐

