openFrameworks + HTTP requests + XML parser

So you want to pull tweets from the Twitter API or collect news from RSS feeds? All it takes is a little HTTP work and XML parsing. As fast as openFrameworks is growing, it’s definitely not the most stable or the easiest to work with. The following is documentation of the tinkering it took to get happy tweets to show up in my oF app. I mention Twitter only as an example; the following allows you to interact with basically any web service.

There’s no need for a service-specific library; existing oF addons provide all we need. That said, the project will need these addons.

The following was done on Ubuntu 9.10 in Codeblocks with oF v0.061.

Both ofxThread and ofxXmlSettings come as part of the FAT package. As of v0.061, creating new oF projects and incorporating addons is still a tacky process but I’m sure this process will get smoothed out in the future. As of writing, ofxHttpUtils is at v0.2 and not part of the FAT package. It’s also not compatible with the changes made by v0.06.

In ofxHttpUtils.h, remove/comment the #include ofAddons.h and add an #include ofxThread.h. I’m pretty sure this has to do with the changes to the addon infrastructure changes by v0.06. To be thorough, the #define OF_ADDON_USING_OFXTHREAD is also not needed.

testApp.h

Change testApp.h as follows. Add the includes and note the extra inheritance of ofxHttpEventListener.

#include "ofxHttpEvents.h"
#include "ofxXmlSettings.h"

class testApp : public ofBaseApp, public ofxHttpEventListener {
    public:
...
        void newResponse(ofxHttpResponse &response);
...
        ofxXmlSettings XML;
};

testApp.cpp

The remaining changes reside in testApp.cpp. Add the following line in the setup method. This registers the testApp object as the callback for the HTTP requests.

void testApp::setup() {
...
    ofxHttpEvents.addListener(this);
...
}

Implement the success callback function (there is also a newError you should implement). The response object contains the usual HTTP data, of which responseBody is probably the most interesting. The following code inside the function processes the responseBody string as XML and outputs the desired data. In this example, the for loop iterates through <entry> nodes and prints the respective title and published node values. For the Twitter ATOM feed, this happens to print the tweets and the published date times.

void testApp::newResponse(ofxHttpResponse &response) {
    // printf("%s\n", response.responseBody.c_str());

    XML.loadFromBuffer(response.responseBody); // parse string
    XML.pushTag("feed"); // change relative root to <feed>

    int numEntries = XML.getNumTags("entry");
    // iterate through <entry> tags
    for (int i = 0; i < numEntries; i++) {
        printf("%s\n", XML.getValue("entry:title", "", i).c_str());
        printf("%s\n", XML.getValue("entry:published", "", i).c_str());
    }
    XML.popTag(); // move out of <feed>
}

Now that the callback is set, send HTTP requests with the following line. This will spawn a new thread to perform the HTTP request followed by the appropriate callback.

ofxHttpUtil.addUrl("http://search.twitter.com/search.atom?q=beatles");

This initiates a GET request but POST requests with parameters are not much harder. Scour the source code of ofxHttpUtils and ofxXmlSettings. I’m sure the oF documentation will improve but for now, oF works for tinkerers; reading code and putting the pieces together is just part of the process.

評論