【问题标题】:Iterate through PTree children w/o including tag name遍历不包含标签名称的 PTree 子项
【发布时间】:2020-11-26 23:49:45
【问题描述】:

我想知道是否有一种方法可以通过遍历父节点的向量来获取子节点中的数据。我有一个我计划经常更改的 XML 文件,因此我想避免对属性名称进行硬编码。因此,我想在我的子节点中提取数据而不使用pt.get_child(myparentNodes) 说明节点的标记名称。我主要有这个。

非常感谢任何帮助!

vector<string> parentNodes;
ptree pt;
ifstream fileName("myxml");
read_xml(fileName, pt);

for(const ptree::value_type &parent : pt)
{
    cout << parent.first << std::endl;
    parentNodes.push_back(parent.first);
  
}
 for(int i=0; i<parentNodes.size();i++)
 {
BOOST_FOREACH(boost::property_tree::ptree::value_type const &node,pt.get_child(parentNodes[i]))

/* I'm having trouble properly accessing the children nodes here */

【问题讨论】:

    标签: c++ xml visual-studio boost ptree


    【解决方案1】:

    在你的 sn-p 中(稍微清理一下):

    std::vector<std::string> parentNodes;
    for(auto const& parent : pt) {
        std::cout << parent.first << std::endl;
        parentNodes.push_back(parent.first);
    }
    

    似乎正在将树节点的名称收集到parentNodes。但是,这假定名称是唯一的或非空的。

    属性名称不必是唯一的,也不保证它们不为空。事实上,Property Tree 中的数组经常被建模为只有未命名子节点的节点。

    那么您在获取相应节点的子节点时遇到了麻烦。让我们首先以乏味的方式来做(同样,假设名称是唯一的):

    for (size_t i = 0; i < parentNodes.size(); i++) {
        auto& parent = pt.get_child(parentNodes[i]);
    
        for (auto const& child : parent) {
            std::cout << child.first << std::endl;
        }
    }
    

    当然使用 ranged-for 要容易得多:

    for (auto const& name : parentNodes) {
        auto& parent = pt.get_child(name);
    
        for (auto const& child : parent) {
            std::cout << child.first << std::endl;
        }
    }
    

    更好

    您可以避免关于命名以及第二个循环和向量存储的假设:

    for (auto const& parent : pt) {
        std::cout << parent.first << std::endl;
    
        auto& node = parent.second;
        for (auto const& child : node) {
            std::cout << child.first << std::endl;
        }
    }
    

    这是因为迭代器指向一对(key, value)。事实上,在最近的编译器上,您可以使用结构化绑定编写循环:

    for (auto const& [name, node] : pt) {
        std::cout << name << std::endl;
    
        for (auto const& child : node) {
            std::cout << child.first << std::endl;
        }
    }
    

    还在做同样的事情。

    概括

    你说过你想让这个通用。但是,假设父/子关系的两层层次结构并不让我觉得“通用”。我将您链接到一些显示通用遍历的示例(例如,在整个树中寻找模式)last time,例如Iterating on xml file with boost - 该示例中的函数:

    Live On Wandbox

    #include <boost/property_tree/xml_parser.hpp>
    #include <iostream>
    
    using boost::property_tree::ptree;
    static auto settings = boost::property_tree::xml_writer_make_settings<std::string>(' ', 4);
    
    template <typename Out>
    Out enumerate_nodes(ptree const& pt, ptree::path_type path, Out out) {
        if (path.empty())
            return out;
    
        if (path.single()) {
            auto name = path.reduce();
            for (auto& child : pt) {
                if (child.first == name)
                    *out++ = child.second;
            }
        } else {
            auto head = path.reduce();
            for (auto& child : pt) {
                if (head == "*" || child.first == head) {
                    out = enumerate_nodes(child.second, path, out);
                }
            }
        }
    
        return out;
    }
    
    int main() {
        std::ifstream fileName("input.xml");
        ptree pt;
        read_xml(fileName, pt);
    
        for (auto const& [name, node] : pt) {
            std::cout << name << std::endl;
    
            for (auto const& child : node)
                std::cout << child.first << std::endl;
        }
    
        std::vector<std::reference_wrapper<ptree const>> matched;
        enumerate_nodes(pt, "root.parent2.child3", back_inserter(matched));
    
        for (ptree const& match : matched)
            std::cout << "Matched: " << match.get_value<std::string>() << "\n";
    }
    

    使用input.xml时:

    <?xml version="1.0"?>
    <root>
        <parent1>
            <child1>parent1/child1</child1>
            <child2>parent1/child2</child2>
            <child3>parent1/child3</child3>
            <child4>parent1/child4</child4>
        </parent1>
        <parent2>
            <child1>parent2/child1</child1>
            <child2>parent2/child2</child2>
            <child3>parent2/child3</child3>
            <child4>parent2/child4</child4>
        </parent2>
        <parent3>
            <child1>parent3/child1</child1>
            <child2>parent3/child2</child2>
            <child3>parent3/child3</child3>
            <child4>parent3/child4</child4>
        </parent3>
        <parent4>
            <child1>parent4/child1</child1>
            <child2>parent4/child2</child2>
            <child3>parent4/child3</child3>
            <child4>parent4/child4</child4>
        </parent4>
    </root>
    

    打印

    root
    parent1
    parent2
    parent3
    parent4
    Matched: parent2/child3
    

    【讨论】:

      猜你喜欢
      • 2023-03-03
      • 1970-01-01
      • 2018-07-11
      • 2011-10-03
      • 1970-01-01
      • 1970-01-01
      • 2014-11-04
      • 2015-09-08
      • 1970-01-01
      相关资源
      最近更新 更多