How to parse xml from a http xml response?



  • Hello,

    I make http call to server using QNetworkAccessManager and I get in QNetworkReply XML data of next form:
    <response>
    <status>STATUS_CODE</status>
    <item1>VALUE1</item1>
    </response>

    How can I parse QNetworkReply and get values STATUS_CODE and VALUE1?
    Does next code parse xml values :

    @void Sample::parseXml(QNetworkReply reply)
    {
    qDebug()<<reply->readAll();
    QDomDocument
    doc = new QDomDocument();
    if(doc->setContent(reply)){
    QDomElement docElem =doc->documentElement();
    QDomNode n = docElem.firstChild();
    while(!n.isNull()) {
    QDomElement e = n.toElement(); // try to convert the node to an element.
    if(!e.isNull()) {
    qDebug() << qPrintable(e.tagName())<< endl;// the node really is an element.
    }
    n = n.nextSibling();
    }
    }
    }@
    ?

    Thank you for your answer.



  • [quote author="Pavel Mazniker" date="1328549678"]
    Does next code parse xml values?[/quote]

    Well, did you try it?

    Honestly if it is just the two fields use a regular expression instead. This saves you the dependency to QtXml and a full-blown DOM document each time you have to parse a reply.
    @
    QRegExp exp("s>(.*)</s.1>(.)</i");
    exp.indexIn(reply->readAll());
    if(exp.captureCount() == 2)
    {
    QString statusCode = exp.cap(1);
    QString value1 = exp.cap(2);
    }
    @



  • Hi Lukas,

    not yet tryed but I found the questionin another Qt forum where it wasn't answered a lot of time and I begun to code similar class.

    It is nice solution to use QRegExp in this case.Thanks.I'll try it.

    I have another question , basically when I call
    @
    networkAccessManager->get(QNetworkRequest(url));
    @
    I should await for reply ready when next signal called:
    @
    networkAccessManager->finished(QNetworkReply*);
    @
    how can I wait in code till reply?
    Can I use
    @
    while(...)
    { QApplication::processEvents() ;
    }
    @
    loop ? Any good suggestions how to wait till response process it in slot and continue processing it in the same method where networkAccessManager->get(QNetworkRequest(url)); called?

    Thanks

    Edit: some formatting fixes; Andre





  • thanks I'll check.
    I didn't understand yet next
    @QRegExp exp("s>(.*)</s.1>(.)</i");@

    I run that code on file it returns "" in cap(1-3).

    Could you please explain how you've constructed the expression?

    What expression should be for next xml text stream:
    @<plimus_licensing_response>
    <status>SUCCESS</status>
    <days_till_expiration>44</days_till_expiration>
    <use_count>107</use_count>
    </plimus_licensing_response>@

    Regards...



  • <code>(</code> and <code>)</code> define so called capture groups, which are accessible using QRegExp::cap(). In our case it captures every character combination <code>.</code>, limited by the (shortened) start (<statu s>) and end (</s* tatus>) element.

    So the regular expression for the second xml stream would be
    @
    QRegExp exp("<status>(.)</status>.<days_till_expiration>(.)</days_till_expiration>.<use_count>(.)</use_count>");
    @
    or shortened
    @
    QRegExp exp("s>(.
    )</s.n>(.)</d.t>(.)</u");
    @



  • I'm really not a fan of using regular expressions to parse XML. IMHO, it makes the code fragile and hard to read. If you use [[doc:QXmlStreamReader]] you don't have to link to the QtXML module. This class is in QtCore.



  • While one might get the raw content between the opening and closing tags using regular expressions, it is still the raw content. You need to do entity replacement manually (don't tell that doesn't happen - it will and it will bite you eventually). So adding that, bloats the code, eventually doubling functionality that's already in Qt and that's well tested.

    PS:
    @Pavel
    It's usually a bad idea to ask a forum wether a code snippet will work when you didn't try it yourself yet. That will annoy otherwise helpful people and make it likely to ignore your question at all. You're supposed to do your homework. Creating a small test case for such a short snippet shouldn't be too hard.



  • Just for the record: regular expressions are not a replacement for full-featured XML parsing.

    However, I would prefer them to parse two static values out of a well-defined three-liner, as long as you aware of the fact that it doesn't scale.



  • Would you mind explaining that preference? Why would you choose regexps over using real XML parsing?

    I think something to keep in mind is, that XML is by its very nature extendable. That is: it could contain more than you took into account, and instead of that causing an error, the additional data should be ignored. Also, I think that readability of code is very important, I find regular expressions very hard to read indeed. Still, perhaps you have good reasons for this choice?



  • I would not say it is a general preference, but in this specific case I would prefer a simple regular expression over QDomDocument, because it is just a waste of resources. QXmlStreamReader might be a viable option, but it still requires me to write a multitude of code just to remove some character padding around a string and an integer value (and I can hardly think of anything more extendable then a nongreedy regular expression match combined with <code>.*</code>).

    Yes, regular expressions should not be used as a replacement for XML parsing in general, when it comes to different encodings, a varying document structure, schema validation, optional elements and attributes and all the other gruesomeness of XML, but in this specific case ("... if it is just the two fields ..."), where two basic datatypes are paddad by some well-defined and static characters, a simple regular expression is a readable (subjective, I agree on that to a certain degree), extension-resistant single-line construct.

    This conclusion will change if the conditions change.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.