c++xmlrapidxml

getting nested values from a decoded SAMLresponse XML with rapidxml


I have been trying to get the values of the decoded XML, all 3 of them.

The XML file is as follows (it has way more nodes but this is just a testing preview)

<Response ID="number" Version="2.0">
    <Issuer xmlns=":assertion">
        check1
    </Issuer>
    <Status>
        <StatusCode Value="Success" />
        checkcheck2
    </Status>
    <Assertion ID="somenumber" IssueInstant="datestamp" Version="2.0"
        xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
        <Issuer>
            checkcheckcheck3
        </Issuer>
    </Assertion>
</Response> 

I tried to get the value out off the "Status" node in the following way (don't mind the includes I don't need I have been trying a lot of things and just keep them for now incase I need them, will remove them when it is working):

#include <iostream>
#include <sstream>
#include <iostream>
#include <cstring>
#include <string>
#include <fstream>
#include <vector>
#include "rapidxml.hpp"
#include "rapidxml_print.hpp"
#include "base64.hpp"

using namespace std;
    int main()
    {
        rapidxml::xml_node<> *root_node;
        rapidxml::xml_node<> *second_node;
        
                
        //costum base64 encoder and decoder this works as it should
        help::base64_decode;
    
        string xmlFile;
    
        // Base64 response from form data contains xml
        xmlFile = help::base64_decode("the base64 encoded SAMLResponse");
    
        //put the b64 decoded xml in a string
        stringstream decodedXml(xmlFile);
        rapidxml::xml_document<> doc;
    
        // test the decoded b64
        cout << xmlFile << endl;
    
        // Read file into vector<char>
        vector<char> buffer((istreambuf_iterator<char>(decodedXml)), istreambuf_iterator<char>());
    
        buffer.push_back('\0');
    
        doc.parse<0>(&buffer[0]);
    
        root_node = doc.first_node("Response");
    
    // this returs Issuer 
        cout << root_node->first_node()->name() << endl;
    
    // go to next sibling of the root node ?? (that should be Status)
        second_node = root_node->next_sibling(); 
    
    // gives me a exited with code=3221225477 in 0.485 seconds on compiling 
        cout << second_node->first_node()->name() << endl;

What am I doing wrong, or rather. What part of the next_sibling() function am I misunderstanding. As far as I know the next_sibling() would go to the next node that is on the same level as the one declared as root_node (which is Issuer in this case).


Solution

  • In case anyone is wondering what i did to fix not being able to search nodes by string input.

    i wrote a function that searches for sibling nodes.

      
    //gets the coun of child nodes present in current node
    int getChildCount(rapidxml::xml_node<> *n)
        {
            int c = 0;
            for (rapidxml::xml_node<> *child = n; child != NULL; child = child->next_sibling())
            {
                c++;
            }
            return c;
        }
        
    
    static rapidxml::xml_node<> *find_sibling(rapidxml::xml_node<> *in, const std::string &s)
        {
            rapidxml::xml_document<> doc_error;
            rapidxml::xml_node<> *err = doc_error.allocate_node(rapidxml::node_element, "error");
            doc_error.append_node(err);
    
            std::string node_name;
    
            int childs = getChildCount(in);
            int count = 1;
    
            while (in != NULL)
            {
    
                in = in->next_sibling();
                count++;
    
                node_name = in->name();
    
                if (node_name == s)
                {
                    return in;
                }
                if (count == childs)
                {
                    return err;
                }
            }
            return err;
        }
    

    This now allows me to search with;

    rapidxml::xml_node<> *issuer_node = find_sibling(issuer_node->first_node(), "Assertion"); This wil go through the function to try and find Assertion node. And if it can not be found it within the sibling nodes instead of just crashing, it returns a xml doc with .