RapidXML
RapidXML is my preferred XML parser. It's fast, has a great api and it's stable. Oh yeah, and it's template based, so no need to compile a library which is sometimes easy.
Including the header
#include <rapidxml.hpp>
using namespace rapidxml
Loading the contents of you XML file
std::ifstream ifs("file.xml", std::ios::in); if(!ifs.is_open()) { return false; } std::string xml_str; xml_str.assign(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());
Create XML instance with the loaded contents
xml_document<> doc; try { doc.parse<0>((char*)xml_str.c_str()); } catch (...) { return false; }
Fetching data
xml_node<>* cfg = doc.first_node("settings"); std::string str = cfg->value();
Fetching attributes
xml_node<>* cfg = doc.first_node("video"); xml_attribute<>* att = cfg->first_attribute("width"); std::string w = att->value();
Iterating over children
<chars count="276"> <char id="32" x="93" y="93" /> <char id="33" x="125" y="23" /> <char id="34" x="30" y="95" /> <char id="35" x="85" y="70" /> <char id="36" x="13" y="35" /> </chars>
xml_node<>* chars = xfont->first_node("chars"); xml_node<>* char = xchars->first_node(); while(xchar) { // do something with the current char char = char->next_sibling(); }
Using a templated function to read different types of values
template <class T> int read_xml(xml_node<>* node, std::string name, T defaultval, T& result) { result = defaultval; if (0 == name.size()) { RX_ERROR("name.size() == 0."); return -1; } if (NULL == node) { RX_ERROR("Container node for %s is NULL.", name.c_str()); return -2; } xml_node<>* el = node->first_node(name.c_str()); if (NULL == el) { RX_ERROR("%s not found in %s", name.c_str(), node->name()); return -3; } std::stringstream ss; ss << el->value(); ss >> result; return 0; }