Assuming you have a target structure like
struct Car {
std::string name, weight;
struct Spec {
std::string serial_, source;
double mileage;
};
std::vector<Spec> specs;
};
I'd write code like
for (auto& [key, node] : pt.get_child("root.type.cars")) {
if ("car" == key) {
Car car;
parse(node, car);
std::cout << car << "\n";
}
}
Where parse
is:
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;
}
And of course, a similar overload for 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";
}
}
}
Prints
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]