Я люблю хранить технологическую конфигурацию моих программ и утилит в XML-файле.
Пока я делал приложения с использованием Qt использовал небольшой класс, который читал эту конфигурацию и сохранял её в QStringMap.
Однако возникла потребность сделать простую утилиту на C++ но без Qt, XML-парсером которой я пользовался.
Типичный формат моего XML таков:
<?xml version="1.0" encoding="utf-8"?> <registry> <version>1</version> <section id="common" > <parameter id="locale" >ru_RU.utf8</parameter> <parameter id="parameter1" >value1</parameter> <parameter id="parameter2" >value2</parameter> </section> </registry>Для чтения я без проблем воспользовался бесплатной библиотекой RapidXML 1.13. Сейчас она входит в Boost, но я попробовал также использовать её и отдельно (при сборке с помощью GNU C++/MinGW под Windows). Собственно библиотека эта состоит из трёх шабонных HPP-файлов, которые не требуют компиляции.
//#include <rapidxml.hpp>
//using namespace rapidxml;
#include <boost/property_tree/detail/rapidxml.hpp>
using namespace boost::property_tree::detail::rapidxml;
// .................
// ---
xml_document<char> doc;
//cout << "Parse..." << endl;
try {
ifstream file( fname_xml.c_str() );
vector<char> buffer((istreambuf_iterator<char>(file)), istreambuf_iterator<char>());
buffer.push_back('\0');
doc.parse<0>( &buffer[0] );
}
catch (parse_error e) {
cerr << "Fail. Parse error " << e.what() << endl;
return 0;
}
xml_node<> *root_node = doc.first_node();
//cout << "Root found?" << endl;
if (root_node!=NULL)
{
//cout << "Root found!" << root_node->name() << ":" << root_node->value() << endl;
xml_node<> *node = root_node->first_node("section");
//if (node!=NULL) cout << "section found" << endl;
if (node) node = node->first_node("parameter");
//if (node!=NULL) cout << "first parameter found" << endl;
while (node!=NULL)
{
xml_attribute<>* a = node->first_attribute("id");
if (a!=NULL)
{
config[ a->value() ] = node->value();
}
node = node->next_sibling();
}
}
cout << "========" << endl << "Check loaded configuration:" << endl;
typedef map<string,string>::const_iterator it;
for (it i=config.begin(); i!=config.end(); i++)
{
cout << i->first << "\t= " << i->second << endl;
}
cout << "Configuration loaded" << endl;
// ---