Search code examples
c++xmlrapidxml

Looping through a node using rapidxml


I'm new to using XML with C++ and I want to loop through an XML node and print the 'id' attribute of into a vector. This is my XML

<?xml version="1.0" encoding="UTF-8"?>
<player playerID="0">
    <frames>
        <frame id="0"></frame>
        <frame id="1"></frame>
        <frame id="2"></frame>
        <frame id="3"></frame>
        <frame id="4"></frame>
        <frame id="5"></frame>
    </frames>
</player>

and this is how I'm loading the XML

rapidxml::xml_document<> xmlDoc;

/* "Read file into vector<char>"*/
std::vector<char> buffer((std::istreambuf_iterator<char>(xmlFile)), std::istreambuf_iterator<char>( ));
buffer.push_back('\0');
xmlDoc.parse<0>(&buffer[0]);

How do I loop through the node?


Solution

  • Once you've loaded xml into your document object, you can use first_node() to get specified child node (or just the first one); then you can use next_sibling() to go through all its siblings. Use first_attribute() to get node's specified (or just first) attribute. This is an idea of how the code could look like:

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <sstream>
    #include <rapidxml.hpp>
    using std::cout;
    using std::endl;
    using std::ifstream;
    using std::vector;
    using std::stringstream;
    using namespace rapidxml;
    
    int main()
    {
        ifstream in("test.xml");
    
        xml_document<> doc;
        std::vector<char> buffer((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>( ));
        buffer.push_back('\0');
        doc.parse<0>(&buffer[0]);
    
        vector<int> vecID;
    
        // get document's first node - 'player' node
        // get player's first child - 'frames' node
        // get frames' first child - first 'frame' node
        xml_node<>* nodeFrame = doc.first_node()->first_node()->first_node();
    
        while(nodeFrame)
        {
            stringstream ss;
            ss << nodeFrame->first_attribute("id")->value();
            int nID;
            ss >> nID;
            vecID.push_back(nID);
            nodeFrame = nodeFrame->next_sibling();
        }
    
        vector<int>::const_iterator it = vecID.begin();
        for(; it != vecID.end(); it++)
        {
            cout << *it << endl;
        }
    
        return 0;
    }