【问题标题】:Parsing a nested XML file for its attributes using BOOST library in c++使用 C++ 中的 BOOST 库解析嵌套 XML 文件的属性
【发布时间】:2021-05-23 22:32:22
【问题描述】:

我的 XML 文件嵌套如下:

<?xml version="1.0" encoding="utf-8"?>
<root>
<type>
<cars>
<car name="Garfield" weight="4Kg">
<spec serial_="e_54" source ="petrol" mileage="56"/>
<spec serial_="e_52" source="diesel" mileage="52"/>
<spec serial_="m_22" source="electric" mileage="51"/>
<additions source="steam" convert="153 0 1 0"/>
</car>
<car name="Awesome" weight="3Kg">
<spec serial_="t_54" source="petrol" mileage="16"/>
<spec serial_="t_52" source="wind" mileage="62"/>
<spec serial_="t_22" source="electric" mileage="81"/>
<additions source="water" convert="123 1 1 0"/>
</car>
</cars>
<planes>
<plane id="231" name ="abc">
<utilities serial_="e456" part="567"/>
</plane>
</type>
</root>

我希望获取“汽车”下的所有“汽车”属性。此外,我还希望获取其所有子节点“规范”的属性。

目前,我的代码类似于此问题中的代码: Parsing nested xml with boost

我能够获得“汽车”标签的属性。但是,我无法获取其子元素的属性。即使我成功获取了第一个“汽车”所需的所有数据,它也会继续打印与第一个节点相同的子属性。

【问题讨论】:

标签: c++ xml boost xml-parsing boost-propertytree


【解决方案1】:

假设你有一个像这样的目标结构

struct Car {
    std::string name, weight;
    struct Spec {
        std::string serial_, source;
        double mileage;
    };
    std::vector<Spec> specs;
};

我会写这样的代码

for (auto& [key, node] : pt.get_child("root.type.cars")) {
    if ("car" == key) {
        Car car;
        parse(node, car);
        std::cout << car << "\n";
    }
}

parse 在哪里:

static bool parse(ptree const& node, Car& into)  {
    into.name   = node.get<std::string>("<xmlattr>.name");
    into.weight = node.get<std::string>("<xmlattr>.weight");
    for (auto& [name, child] : node) {
        if (name == "spec") {
            into.specs.emplace_back();
            if (!parse(child, into.specs.back())) {
                return false;
            }
        }
    }
    return true;
}

当然,Spec 也有类似的重载:

static bool parse(ptree const& node, Car::Spec& into) {
    into.serial_ = node.get<std::string>("<xmlattr>.serial_");
    into.source  = node.get<std::string>("<xmlattr>.source");
    into.mileage = node.get<double>("<xmlattr>.mileage");
    return true;
}

Live Demo

#include <boost/property_tree/xml_parser.hpp>
using boost::property_tree::ptree;
#include <iostream>

struct Car {
    std::string name, weight;
    struct Spec {
        std::string serial_, source;
        double mileage;
    };
    std::vector<Spec> specs;
};

static bool parse(ptree const& node, Car::Spec& into) {
    into.serial_ = node.get<std::string>("<xmlattr>.serial_");
    into.source  = node.get<std::string>("<xmlattr>.source");
    into.mileage = node.get<double>("<xmlattr>.mileage");
    return true;
}

static bool parse(ptree const& node, Car& into)  {
    into.name   = node.get<std::string>("<xmlattr>.name");
    into.weight = node.get<std::string>("<xmlattr>.weight");
    for (auto& [name, child] : node) {
        if (name == "spec") {
            into.specs.emplace_back();
            if (!parse(child, into.specs.back())) {
                return false;
            }
        }
    }
    return true;
}

static std::ostream& operator<<(std::ostream& os, Car const& car) {
    os << "Name: " << car.name << ", Weight: " << car.weight;
    for (auto& spec : car.specs) {
        os << "\n -- [" << spec.serial_ << "; " << spec.source << "; "
           << spec.mileage << "]";
    }
    return os;
}

int main() 
{
    boost::property_tree::ptree pt;
    {
        std::ifstream ifs("input.xml");
        read_xml(ifs, pt);
    }

    for (auto& [key, node] : pt.get_child("root.type.cars")) {
        if ("car" == key) {
            Car car;
            parse(node, car);
            std::cout << car << "\n";
        }
    }
}

打印

Name: Garfield, Weight: 4Kg
 -- [e_54; petrol; 56]
 -- [e_52; diesel; 52]
 -- [m_22; electric; 51]
Name: Awesome, Weight: 3Kg
 -- [t_54; petrol; 16]
 -- [t_52; wind; 62]
 -- [t_22; electric; 81]

【讨论】:

  • 嗨@sehe,您之前的代码运行良好。再次感谢。但是,当我根据更新的 xml 将成员添加到结构和其他函数时(即“添加”标签和平面组。它报告运行时错误如下:没有像 .convert 这样的节点。请您帮忙
  • 我可以。 Posted。我希望它有所帮助,请考虑阅读meta.stackexchange.com/questions/5234/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-10
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多