C++ で libcurl と libxml2 使ってみる
まぁつまりは、C++ で API 叩いて XML をパースしてみようって話です。
必要なもの
- curl
- libxml2
- g++
- 気力
いらないもの
- 眠気
サンプルコード
#include<string> #include<iostream> #include<curl/curl.h> #include<libxml/xpath.h> #include<libxml/xmlreader.h> #define XPATH "/rss/channel/item/title/text()" using namespace std; size_t callBackFunk(char* ptr, size_t size, size_t nmemb, string* stream) { int realsize = size * nmemb; stream->append(ptr, realsize); return realsize; } int main() { CURL *curl; CURLcode res; curl = curl_easy_init(); string chunk; if (curl) { curl_easy_setopt(curl, CURLOPT_URL, "http://dailynews.yahoo.co.jp/fc/rss.xml"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callBackFunk); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (string*)&chunk); res = curl_easy_perform(curl); curl_easy_cleanup(curl); } if (res != CURLE_OK) { cout << "curl error" << endl; return 1; } xmlDocPtr doc; xmlXPathContextPtr ctx; xmlTextReaderPtr reader; xmlXPathObjectPtr xpobj; if (reader = xmlReaderForDoc((xmlChar*)chunk.c_str(), NULL, NULL, 1) ) { xmlTextReaderRead(reader); xmlTextReaderExpand(reader); if ((doc = xmlTextReaderCurrentDoc(reader))) { if ((ctx = xmlXPathNewContext(doc))) { if ((xpobj = xmlXPathEvalExpression((xmlChar *)XPATH, ctx))) { if (!xmlXPathNodeSetIsEmpty(xpobj->nodesetval)) { xmlNodeSetPtr nodes = xpobj->nodesetval; int size = (nodes) ? nodes->nodeNr : 0; for (int i = 0; i < size; ++i) { if (!xmlXPathNodeSetIsEmpty(nodes)) { xmlNodePtr node = xmlXPathNodeSetItem(nodes, i); if (node->content) { cout << node->parent->name << " => " << node->content << endl; } else { cout << "invalid node" << endl; } } } } xmlXPathFreeObject(xpobj); } xmlXPathFreeContext(ctx); } xmlFreeDoc(doc); } xmlFreeTextReader(reader); } xmlCleanupParser(); return 0; }
何をしているの?
curl
curl は、デフォルトだと標準出力に結果が出てしまうので、
- CURLOPT_WRITEFUNCTION にコールバック関数を
- CURLOPT_WRITEDATA にコールバック関数にて処理されたあとのデータ格納ポインタを
指定し、 CURLOPT_WRITEFUNCTION で指定した関数では ptr に curl で得たデータが入っているので、それを stream にいれてやることでCURLOPT_WRITEDATA で指定した変数に格納されるようになる。
xml
xml のパースには、libxml2 を使い、今回は変数からXMLを読み込ませるので xmlReaderForDoc を使った。
実際に欲しいところを抜き出すには xpath を使って抜き出している。
ビルド
$ g++ curlxml.cpp -lcurl -I/path/to/libxml2 -lxml2
誰得?
たぶん自分にしか需要ない。