Is there any good way (and a simple way too) using Boost to read and write XML files?
I can\'t seem to find any simple sample to read XML files using Boost. Can you
From my experiences lurking on the Boost mailing list, it appears that every time XML comes up as a subject, it is diverted into a discussion about Unicode. However, since there is a potential Unicode library looming right now, I don't think it will take too long for an XML library to appear there.
In the meantime, I too have been using TinyXML.
Interesting link about RapidXML. I'll take a look at that.
You should Try pugixml Light-weight, simple and fast XML parser for C++
The nicest thing about pugixml is the XPath support, which TinyXML and RapidXML lack.
Quoting RapidXML's author "I would like to thank Arseny Kapoulkine for his work on pugixml, which was an inspiration for this project" and "5% - 30% faster than pugixml, the fastest XML parser I know of" He had tested against version 0.3 of pugixml, which has reached recently version 0.42.
Here is an excerpt from pugixml documentation:
The main features are:
Okay, you might ask - what's the catch? Everything is so cute - it's small, fast, robust, clean solution for parsing XML. What is missing? Ok, we are fair developers - so here is a misfeature list:
<?xml version="1.0"?>
<Settings>
<GroupA>
<One>4</One>
<Two>7</Two>
<Three>9</Three>
</GroupA>
<GroupA>
<One>454</One>
<Two>47</Two>
<Three>29</Three>
</GroupA>
<GroupB>
<A>String A</A>
<B>String B</B>
</GroupB>
</Settings>
There is an easy way to read XML with BOOST. This example is with std::wstring:
#include <string>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/foreach.hpp>
bool CMyClass::ReadXML(std::wstring &full_path)
{
using boost::property_tree::wptree;
// Populate tree structure pt:
wptree pt;
std::wstringstream ss; ss << load_text_file(full_path); // See below for ref.
read_xml(ss, pt);
// Traverse pt:
BOOST_FOREACH(wptree::value_type const& v, pt.get_child(L"Settings"))
{
if (v.first == L"GroupA")
{
unsigned int n1 = v.second.get<unsigned int>(L"One");
unsigned int n2 = v.second.get<unsigned int>(L"Two");
unsigned int n3= v.second.get<unsigned int>(L"Three");
}
else if (v.first == L"GroupB")
{
std::wstring wstrA = v.second.get<std::wstring>(L"A");
std::wstring wstrB = v.second.get<std::wstring>(L"B");
}
};
}
To read attributes is just a little bit more complicated.
-
Just for the reference:
std::wstring load_text_file(std::wstring &full_path)
{
std::wifstream wif(full_path);
wif.seekg(0, std::ios::end);
buffer.resize(wif.tellg());
wif.seekg(0);
wif.read(buffer.data(), buffer.size());
return buffer;
}
Boost uses RapidXML as described in chapter XML Parser of page How to Populate a Property Tree:
Unfortunately, there is no XML parser in Boost as of the time of this writing. The library therefore contains the fast and tiny RapidXML parser (currently in version 1.13) to provide XML parsing support. RapidXML does not fully support the XML standard; it is not capable of parsing DTDs and therefore cannot do full entity substitution.
Please also refer to the XML boost tutorial.
As the OP wants a "simple way to use boost to read and write xml files", I provide below a very basic example:
<main>
<owner>Matt</owner>
<cats>
<cat>Scarface Max</cat>
<cat>Moose</cat>
<cat>Snowball</cat>
<cat>Powerball</cat>
<cat>Miss Pudge</cat>
<cat>Needlenose</cat>
<cat>Sweety Pie</cat>
<cat>Peacey</cat>
<cat>Funnyface</cat>
</cats>
</main>
(cat names are from Matt Mahoney's homepage)
The corresponding structure in C++:
struct Catowner
{
std::string owner;
std::set<std::string> cats;
};
read_xml() usage:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
Catowner load(const std::string &file)
{
boost::property_tree::ptree pt;
read_xml(file, pt);
Catowner co;
co.owner = pt.get<std::string>("main.owner");
BOOST_FOREACH(
boost::property_tree::ptree::value_type &v,
pt.get_child("main.cats"))
co.cats.insert(v.second.data());
return co;
}
write_xml() usage:
void save(const Catowner &co, const std::string &file)
{
boost::property_tree::ptree pt;
pt.put("main.owner", co.owner);
BOOST_FOREACH(
const std::string &name, co.cats)
pt.add("main.cats.cat", name);
write_xml(file, pt);
}
Boost does not provide an XML parser atm.
Poco XML (part of the Poco C++ libs) is good and simple.
Definatelly use TinyXML *thumbs up*