確か、2〜3年くらい前にCで書いた簡易RSSリーダー。IBMのdeveloperWorksの記事を参考に、Linuxでlibcurlを使ってダウンロードしたRSSフィードをlibxml2を使って解析しながら記事のタイトルとリンク先を表示するというのをやってXMLを学習したような気がするけど、XMLの解析処理をどうやって書いたかさっぱり思い出せないorz
#サンプルコード
libcurlによるRSSフィードのダウンロードはIBMのサンプルをほぼそのまま使って、ダウンロード結果を表示する所を、アップルのRSSフィードのサマリが出るようにしています。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <sys/types.h>
#include <errno.h>
#include <libxml/xmlerror.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#define MAX_BUF 65536
char wr_buf[MAX_BUF+1];
int wr_index;
#define PATH "http://www.apple.com/jp/main/rss/hotnews/hotnews.rss"
/*
* Write data callback function (called within the context of
* curl_easy_perform.
*/
size_t write_data( void *buffer, size_t size, size_t nmemb, void *userp ) {
int segsize = size * nmemb;
if (wr_index + segsize > MAX_BUF) {
*(int *)userp = 1;
return 0;
}
memcpy( (void *)&wr_buf[wr_index], buffer, (size_t)segsize );
wr_index += segsize;
wr_buf[wr_index] = 0;
return segsize;
}
/*
* Parse RSS and print summary.
*/
int
print_rss(char* text) {
int i;
int size;
xmlDoc *doc;
xmlXPathContextPtr xpathCtx;
xmlXPathObjectPtr xpathObj;
xmlNodeSetPtr nodes;
xmlNode *node;
xmlChar *textcount;
/* parse an XML in-memory document and build a tree. */
doc = xmlReadMemory(text, strlen(text), "noname.xml", NULL, 0);
if (doc == NULL) {
perror("xmlReadFile");
return -1;
}
/* Create a new xmlXPathContext */
xpathCtx = xmlXPathNewContext(doc);
if (xpathCtx == NULL) {
perror("xmlXPathNewContext");
xmlFreeDoc(doc);
xmlCleanupParser();
return -1;
}
/* Get Node list of RSS channel */
xpathObj = xmlXPathEvalExpression(BAD_CAST "/rss/channel", xpathCtx);
nodes = xpathObj->nodesetval;
if (nodes == NULL) {
xmlXPathFreeContext(xpathCtx);
xmlFreeDoc(doc);
xmlCleanupParser();
return -1;
}
/* Get and print Title of RSS Feed. */
size = nodes->nodeNr;
for (i = 0; i < size; i++) {
node = xmlFirstElementChild(nodes->nodeTab[i]);
if (node == NULL) {
continue;
}
for (; node; node = xmlNextElementSibling(node)) {
if (strcmp((char*)node->name, "title")) {
continue;
}
textcount = xmlNodeGetContent(node);
if (textcount) {
printf("\nTitle: %s\n\n", textcount);
xmlFree(textcount);
}
}
}
xmlXPathFreeObject(xpathObj);
/* Get Node list of RSS items */
xpathObj = xmlXPathEvalExpression(BAD_CAST "/rss/channel/item", xpathCtx);
nodes = xpathObj->nodesetval;
if (nodes == NULL) {
xmlXPathFreeContext(xpathCtx);
xmlFreeDoc(doc);
xmlCleanupParser();
return -1;
}
/* Get and print title and link of each items. */
size = nodes->nodeNr;
for (i = 0; i < size; i++) {
node = xmlFirstElementChild(nodes->nodeTab[i]);
if (node == NULL) {
continue;
}
for (; node; node = xmlNextElementSibling(node)) {
if (strcmp((char*)node->name, "title") != 0 &&
strcmp((char*)node->name, "link") != 0) {
continue;
}
textcount = xmlNodeGetContent(node);
if (textcount) {
printf(" %s:\t%s\n", node->name, textcount);
xmlFree(textcount);
}
}
printf("\n");
}
xmlXPathFreeObject(xpathObj);
xmlXPathFreeContext(xpathCtx);
xmlFreeDoc(doc);
xmlCleanupParser();
return 0;
}
/*
* Simple curl application to read the rss feed from a Web site.
*/
int main( void )
{
CURL *curl;
CURLcode ret;
int wr_error;
wr_error = 0;
wr_index = 0;
curl = curl_easy_init();
if (!curl) {
printf("couldn't init curl\n");
return 0;
}
curl_easy_setopt(curl, CURLOPT_URL, PATH);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&wr_error);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
ret = curl_easy_perform(curl);
if ( ret == 0 ) {
//
print_rss(wr_buf);
} else {
printf( "ret = %d (write_error = %d)\n", ret, wr_error );
curl_easy_cleanup(curl);
return 1;
}
curl_easy_cleanup(curl);
return 0;
}
#コンパイル
コンパイルには libcurl-devel と libxml2-devel が必要なので事前にインストールしておきます(CentOSの場合)。コンパイル時は -I オプションによるlibxml2のヘッダファイルの指定と -l オプションによるライブラリの指定が必要です。
$ cc -I/usr/include/libxml2 getrss.c -o getrss -lcurl -lxml2
#実行結果
「アップル - ホットニュース」のサマリが表示されました。
$ ./getrss
Title: アップル - ホットニュース
title: Apple、感圧タッチトラックパッドを搭載した15インチのMacBook Pro、238,800円の新しいiMac Retina 5Kディスプレイモデルを発売
link: http://www.apple.com/jp/pr/library/2015/05/19Apple-Introduces-15-inch-MacBook-Pro-with-Force-Touch-Trackpad-New-1-999-iMac-with-Retina-5K-Display.html
title: 日本郵政グループ、IBM、Apple、日本の高齢者がサービスを通じて家族・地域コミュニティーとつながるために、iPadと専用アプリケーションを提供
link: http://www.apple.com/jp/pr/library/2015/04/30Japan-Post-Group-IBM-and-Apple-Deliver-iPads-and-Custom-Apps-to-Connect-Elderly-in-Japan-to-Services-Family-and-Community.html
title: Apple、第2四半期の業績を発表
link: http://www.apple.com/jp/pr/library/2015/04/27Apple-Reports-Record-Second-Quarter-Results.html
・
・
・