1

I'm trying to parse this string and retrieve the "sid" and the "Type". I have the following code. It is crashing at the get_child line and I'm not entirely sure why...

const boost::property_tree::ptree& empty_ptree(){
static boost::property_tree::ptree t;
return t;
}

int _tmain(int argc, _TCHAR* argv[])
{
struct SXMLElements
{
    std::string strSessionId;
    unsigned int uiTypeOfNotification;
};

std::string strXMLText = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n" 
"<NotificationSet vers=\"1.0\" svcid=\"session\" notid=\"42\">\r\n" "<Notification><![CDATA[<SessionNotification vers=\"1.0\" notid=\"42\">\r\n"
"<Session sid=\"sdfkljdsfkjjsf\">\r\n" "<Property name=\"CharSet\" value=\"UTF-8\"></Property>\r\n" 
"</Session>\r\n" "<Type>5</Type>\r\n" 
"<Time>324242</Time>\r\n" 
"</SessionNotification>]]></Notification>\r\n" 
"</NotificationSet>";

//// Parse the HTTP header Status line.
std::stringstream ss( strXMLText );

boost::property_tree::ptree xmlResponse;
//if (strXMLText.size() > 0)
//{
std::istringstream isResponse (strXMLText);
boost::property_tree::read_xml(isResponse, xmlResponse);
SXMLElements sXmlElem;
//const boost::property_tree::ptree & formats = xmlResponse.get_child("NotificationSet.Notification.Session", empty_ptree());
BOOST_FOREACH( boost::property_tree::ptree::value_type const& v, xmlResponse.get_child("NotificationSet.Notification.SessionNotification.Session") )
{
    sXmlElem.strSessionId = xmlResponse.get<std::string>("<xmlattr>.sid", "");
    sXmlElem.uiTypeOfNotification = xmlResponse.get<unsigned int>("Type", 0);
    //  }
}
//}

return 0;
}

Can anyone spot what I might be doing wrong?

1
  • Hehe. To the edit, I also provided the answer :) Commented May 8, 2015 at 22:47

1 Answer 1

0

The Session attribute cd=""\"o=rrs,o=ces,maxtime=""\"64""\" decodes to

cd="o=rrs,o=ces,maxtime="64" 

which leaves invalid XML.

Regardless, all the ""\" could be replaced by just \"

Besides that, a simple test revealed that Boost Property Tree doesn't like <![CDATA[]]> sections, and rightly so: What does <![CDATA[]]> in XML mean?

In an XML document or external parsed entity, a CDATA section is a section of element content that is marked for the parser to interpret as only character data, not markup. wikipedia

SUMMARY

  • Boost Property Tree is not an XML parsing library (xml parsing using boost)
  • CDATA segments are not XML (so even using an XML library you shouldn't expect to parse it directly)

Live On Coliru

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <iostream>

int main()
{
    std::string const strXMLText = R"(<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <NotificationSet vers="1.0" svcid="session" notid="42">
        <Notification><SessionNotification vers="1.0" notid="42">
                <Session sid="sdfkljdsfkjjsf" stype="user" cid="uid=1,u=People,dc=r,dc=c" cd="o=rrs,o=ces,maxtime=64" maxidle="24">
                    <Property name="CharSet" value="UTF-8"></Property>
                    <Property name="ed" value="xxx"></Property>
                    <Property name="Sdle" value="sdl:asdadsad"></Property>
                </Session>
                <Type>5</Type>
                <Time>324242</Time>
        </SessionNotification></Notification>
    </NotificationSet>
    )";

    //// Parse the HTTP header Status line.
    std::stringstream ss(strXMLText);

    boost::property_tree::ptree xmlResponse;

    std::istringstream isResponse (strXMLText);
    boost::property_tree::read_xml(isResponse, xmlResponse);

    if (auto SessionNotification = xmlResponse.get_child_optional("NotificationSet.Notification.SessionNotification"))
    {
        struct SessionElement {
            std::string id;
            unsigned int uiTypeOfNotification;
        };

        if (auto Session = SessionNotification->get_child_optional("Session")) {
            SessionElement elem {
                Session->get("<xmlattr>.sid", ""),
                SessionNotification->get("Type", 0u)
            };

            std::cout << "id: " << elem.id << ", type: " << elem.uiTypeOfNotification << "\n";
        }
    }
}

Prints

id: sdfkljdsfkjjsf, type: 5
Sign up to request clarification or add additional context in comments.

11 Comments

std::string strXMLText = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n" "<NotificationSet vers=\"1.0\" svcid=\"session\" notid=\"42\">\r\n" "<Notification><![CDATA[<SessionNotification vers=\"1.0\" notid=\"42\">\r\n" "<Session sid=\"sdfkljdsfkjjsf\">\r\n" "<Property name=\"CharSet\" value=\"UTF-8\"></Property>\r\n" "</Session>\r\n" "<Type>5</Type>\r\n" "<Time>324242</Time>\r\n" "</SessionNotification>]]></Notification>\r\n" "</NotificationSet>";
That's what I have now Sehe, but i'm getting an exception still being thrown in the "xmlResponse.get_child("NotificationSet.Notification.SessionNotification.Session")" part.....
Because of the CDATA, does that mean i can't use Boost Property Tree? What else could i use?
Please, @suzan, update your question. Comments don't work for this - at all. I've updated my answer
Thanks @sehe, i've updated my code. The xml i initially had with the CDATA was from a demo HTTP POST request with content set to xml. Are you saying that when i receive the POST request with the xml content, that the CDATA won't be in there?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.