【问题标题】:How to iterate a boost property tree?如何迭代提升属性树?
【发布时间】:2011-06-02 23:22:05
【问题描述】:

我知道正在接近 boost 属性树,并看到它是用于 c++ 编程的 boost 库的一个很好的特性。

嗯,我有一个疑问?如何使用迭代器或类似方法迭代属性树?

在参考中只是一个浏览树的例子:

BOOST_FOREACH

但是没有别的了吗?类似于 stl 的容器之类的东西?这将是一个更好的解决方案,谈到代码质量......

【问题讨论】:

    标签: c++ xml iterator boost-propertytree


    【解决方案1】:

    这是我经过大量实验后得出的结论。我想在社区中分享它,因为我找不到我想要的东西。每个人似乎都只是从 boost 文档中发布了答案,我发现这还不够。总之:

    #include <boost/property_tree/ptree.hpp>
    #include <boost/property_tree/json_parser.hpp>
    #include <string>
    #include <iostream>
    
    using namespace std; 
    using boost::property_tree::ptree; 
    
    string indent(int level) {
      string s; 
      for (int i=0; i<level; i++) s += "  ";
      return s; 
    } 
    
    void printTree (ptree &pt, int level) {
      if (pt.empty()) {
        cerr << "\""<< pt.data()<< "\"";
      }
    
      else {
        if (level) cerr << endl; 
    
        cerr << indent(level) << "{" << endl;     
    
        for (ptree::iterator pos = pt.begin(); pos != pt.end();) {
          cerr << indent(level+1) << "\"" << pos->first << "\": "; 
    
          printTree(pos->second, level + 1); 
          ++pos; 
          if (pos != pt.end()) {
            cerr << ","; 
          }
          cerr << endl;
        } 
    
       cerr << indent(level) << " }";     
      }
    
      return; 
    }
    
    int main(int, char*[]) {
    
      // first, make a json file:
      string tagfile = "testing2.pt"; 
      ptree pt1;
      pt1.put("object1.type","ASCII");  
      pt1.put("object2.type","INT64");  
      pt1.put("object3.type","DOUBLE");  
      pt1.put("object1.value","one");  
      pt1.put("object2.value","2");  
      pt1.put("object3.value","3.0");  
      write_json(tagfile, pt1); 
    
      ptree pt;
      bool success = true; 
    
      try {
          read_json(tagfile, pt); 
          printTree(pt, 0); 
          cerr << endl; 
      }catch(const json_parser_error &jpe){
          //do error handling
          success = false
      }
    
      return success; 
    }
    

    这是输出:

    rcook@rzbeast (blockbuster): a.out
    {
      "object1": 
      {
        "type": "ASCII",
        "value": "one"
       },
      "object2": 
      {
        "type": "INT64",
        "value": "2"
       },
      "object3": 
      {
        "type": "DOUBLE",
        "value": "3.0"
       }
     }
    rcook@rzbeast (blockbuster): cat testing2.pt 
    {
        "object1":
        {
            "type": "ASCII",
            "value": "one"
        },
        "object2":
        {
            "type": "INT64",
            "value": "2"
        },
        "object3":
        {
            "type": "DOUBLE",
            "value": "3.0"
        }
    }
    

    【讨论】:

      【解决方案2】:

      BOOST_FOREACH 只是一种方便的迭代方式,可以通过迭代器、begin() 和 end() 完成

      Your_tree_type::const_iterator end = tree.end();
      for (your_tree_type::const_iterator it = tree.begin(); it != end; ++it)
          ...
      

      从 C++11 开始就是:

      for (auto& it: tree)
          ...
      

      【讨论】:

      • 我下午考...啊,没想到这么简单...我会尽快通知你的:)
      • ptree 的顶层,迭代所有需要递归的叶子
      • C++11 示例的符号可以改进:it 现在是 ptree 的子节点,而不是第一个示例中的迭代器。
      • 第二个例子中有趣的部分是 ... 或 auto。详情请见below
      【解决方案3】:

      我最近遇到了这个问题,发现答案不适合我的需要,所以我想出了这个简短而甜蜜的 sn-p:

      using boost::property_tree::ptree;
      
      void parse_tree(const ptree& pt, std::string key)
      {
        std::string nkey;
      
        if (!key.empty())
        {
          // The full-key/value pair for this node is
          // key / pt.data()
          // So do with it what you need
          nkey = key + ".";  // More work is involved if you use a different path separator
        }
      
        ptree::const_iterator end = pt.end();
        for (ptree::const_iterator it = pt.begin(); it != end; ++it)
        {
          parse_tree(it->second, nkey + it->first);
        }
      }
      

      需要注意的重要一点是,除了根节点之外的任何节点都可以包含数据以及子节点。 if (!key.empty()) 位将获取除根节点以外的所有节点的数据,如果有的话,我们也可以开始构建该节点的子节点的循环路径。

      您可以通过调用 parse_tree(root_node, "") 开始解析,当然您需要在此函数中做一些事情以使其值得做。

      如果您在不需要完整路径的情况下进行一些解析,只需删除 nkey 变量及其操作,然后将 it-&gt;first 传递给递归函数即可。

      【讨论】:

        【解决方案4】:

        答案How to iterate a boost property tree?的补充:

        在基于 for (auto node : tree) 的 C++11 样式范围内,每个 node 都是一个 std::pair&lt;key_type, property_tree&gt;

        而在手动编写的迭代中

        Your_tree_type::const_iterator end = tree.end();
        for (your_tree_type::const_iterator it = tree.begin(); it != end; ++it)
        ...
        

        迭代器it 是指向这样一对的指针。用法上的差别很小。例如,要访问密钥,可以写it-&gt;firstnode.first

        作为新答案发布,因为我提议的对原始答案的修改被拒绝并建议发布新答案。

        【讨论】:

          【解决方案5】:

          基于 BFS 的打印 ptree 遍历,如果我们想做一些算法操作可以使用

          int print_ptree_bfs(ptree &tree) {
          try {
              std::queue<ptree*> treeQ;
              std::queue<string> strQ;
          
              ptree* temp;
          
              if (tree.empty())
                  cout << "\"" << tree.data() << "\"";
          
              treeQ.push(&tree);
              //cout << tree.data();
              strQ.push(tree.data());
          
              while (!treeQ.empty()) {
                  temp = treeQ.front();
                  treeQ.pop();
          
                  if (temp == NULL) {
                      cout << "Some thing is wrong" << std::endl;
                      break;
                  }
                  cout << "----- " << strQ.front() << "----- " << std::endl;
                  strQ.pop();
          
                  for (auto itr = temp->begin(); itr != temp->end(); itr++) {
                      if (!itr->second.empty()) {
                          //cout << itr->first << std::endl;
                          treeQ.push(&itr->second);
                          strQ.push(itr->first);
                      } else {
                          cout<<itr->first << " " << itr->second.data() << std::endl;
                      }
                  }
          
                  cout << std::endl;
          
               }
             } catch (std::exception const& ex) {
              cout << ex.what() << std::endl;
             }
             return EXIT_SUCCESS;
            }
          

          【讨论】:

            猜你喜欢
            • 2011-11-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-12-25
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多