0

I have a Qt application where I am trying to download a XML file form a server and then read the content of the file. Unfortunately, I am not able to get the content of the downloaded file in to a QDomDocument.

This is what I tried

QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(fileIsReady(QNetworkReply*)) );
manager->get(QNetworkRequest(QUrl("http://example.com/file.xml")));


fileIsReady(QNetworkReply *reply){

    QTemporaryFile tempFile;
    if(tempFile.open()){
        tempFile.write(reply->readAll());
        QDomDocument versionXML;
        QDomElement root;

        if(!versionXML.setContent(&tempFile)){
            qDebug() << "failed to load version file" << endl;
        }
        else{
            root=versionXML.firstChildElement();
            //...
        }

    }

}

How can I achieve this?

testus
  • 183
  • 2
  • 21
  • Make sure you flush the data and seek back to 0 before setting content. – alediaferia Jan 28 '15 at 15:56
  • Also, `QDomDocument::setContent(QIODevice * dev, bool namespaceProcessing, QString * errorMsg = 0, int * errorLine = 0, int * errorColumn = 0)` gives an easy way to know the actual error message... – alediaferia Jan 28 '15 at 15:57
  • @alediaferia can you tell me what you mean by flushing the data? – testus Jan 28 '15 at 16:19
  • Make sure the data you write from `reply->readAll()` to the temporary file is written actually to the file and not just buffered into memory. You can achieve this by calling `tempFile.flush()` before setting the content. Also, `QDomDocument::setContent` does not give any advice regarding how it uses the `QIODevice*` you pass in so you better `tempFile.seek(0)` before, in order to make sure `QDomDocument` actually reads from the start of the file. – alediaferia Jan 28 '15 at 16:24
  • 2
    Note that the temporary file isn't actually necessary. QNetworkReply inherits from QIODevice, so you can just do `versionXML.setContent(reply)`. – Dan Milburn Jan 28 '15 at 16:25
  • Anyway there's a lot to check here. You also need to check whether you get a valid response from server. Anyway I highly recommend you print out the error message. – alediaferia Jan 28 '15 at 16:26

1 Answers1

1

I think the streaming interfaces are a bit hard to use when you are new to Qt. If you don't have super-big downloads that fit into RAM, just use QByteArray.

fileIsReady(QNetworkReply *reply){
    QByteArray data = reply->readAll();
    qDebug() << "XML download size:" << data.size() << "bytes";
    qDebug() << QString::​fromUtf8(data);

    QDomDocument versionXML;

    if(!versionXML.setContent(data))
    {
        qWarning() << "Failed to parse XML";
    }

    // ...
}
Simon Warta
  • 10,850
  • 5
  • 40
  • 78
  • I tried this but I get **XML download size: 226 bytes Failed to parse QML** as the output everytime. Even if I link to a non-existent file I get the same XML download size. Is the first part of `manager->get(QNetworkRequest(QUrl("http://example.com/file.xml")));` correct? – testus Jan 28 '15 at 17:19
  • Okay good, then have a look what these 226 bytes are. See my edited answer. – Simon Warta Jan 28 '15 at 17:24
  • **Not Acceptable!

    Not Acceptable!

    An appropriate representation of the requested resource could not be found on this server. This error was generated by Mod_Security.

    – testus Jan 28 '15 at 17:28
  • Looks like you need to set a proper `Accept` header in the request. https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields – Simon Warta Jan 28 '15 at 17:31
  • got it using this answer http://stackoverflow.com/questions/14416786/webpage-returning-http-406-error-only-when-connecting-from-qt – testus Jan 28 '15 at 17:32