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).
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 .