c++ 使用rapidxml从编码的SAML回应XML取得巢状值

zazmityj  于 2022-12-05  发布在  其他
关注(0)|答案(2)|浏览(135)

我一直在尝试获取解码后的XML的值,所有3个值。
XML文件如下所示(它有更多的节点,但这只是一个测试预览)

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

我试图以以下方式从“状态”节点中获取值(不要介意包含我不需要的内容,我已经尝试了很多东西,只是暂时保留它们,以防我需要它们,当它工作时将删除它们):

#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;

我做错了什么,或者说,我误解了next_sibling()函数的哪一部分。据我所知,next_sibling()将转到与声明为root_node的节点(在本例中是Issuer)处于同一级别的下一个节点。

qv7cva1a

qv7cva1a1#

根节点--根据定义--不能有兄弟节点。相反,您需要->first_node()->next_sibling和co,或者更好:按名称搜索子节点:

doc.parse<rapidxml::parse_trim_whitespace>(&buffer[0]);

auto root_node = doc.first_node("Response");
auto issuer_node = root_node->first_node("Issuer");
auto status_node = root_node->first_node("Status");
auto assertion_issuer_node = root_node->first_node("Assertion")->first_node("Issuer");

cout << "Issuer: " << issuer_node->value() << endl;
cout << "StatusCode: " << status_node->value() << endl;
cout << "Assertion.Issuer: " << assertion_issuer_node->value() << endl;

注意parse_trim_whitespace的使用,如果没有它,value()函数将包含大量空白。

m4pnthwp

m4pnthwp2#

如果有人想知道我做了什么来修复不能通过字符串输入搜索节点。
我写了一个搜索兄弟节点的函数。

//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;
    }

这现在允许我搜索与;
rapidxml::xml_node<> *issuer_node = find_sibling(issuer_node->first_node(), "Assertion");这将通过函数来尝试并找到Assert节点。如果在兄弟节点中找不到它,而不是崩溃,它将返回一个带有的xml文档。

相关问题