今回は、RSS 0.91 を扱うための処理を RSS リーダーに組み込んでみることにします。
一般的に RSS 0.91 の xml ファイルは、以下のような形式をしています
(注意: 0.91 は rdf ではありません)。
RSS 1.0 と比べるとシンプルです。
(実際には、もっといろんなバリエーションが可能なのですが、ここでは簡単のために最も一般的な例を示しています。)
<?xml version="1.0" encoding="ISO-8859-1" ?> <rss version="0.91"> <channel> <title>RSS の対象となる Web ページのタイトル</title> <link>RSS の対象となる Web ページの URL</link> <description>RSS の対象となる Web ページの概要</description> <language>言語(日本語の場合は ja)</language> <copyright>RSS の対象となる Web ページに関する著作権に関する情報</copyright> <managingEditor>RSS の対象となる Web ページの編集者のemailアドレス</managingEditor> <webMaster>RSS の対象となる Web ページの管理者のemailアドレス</webMaster> <item> <title>RSS 生成対象の 最初 の記事の 題名</title> <link>RSS 生成対象の 最初 の記事の URL</link> <description>RSS 生成対象の 最初 の記事の 概要</description> </item> <item> <title>RSS 生成対象の 2番目 の記事の 題名</title> <link>RSS 生成対象の 2番目 の記事の URL</link> <description>RSS 生成対象の 2番目 の記事の 概要</description> </item> ・・・・・・・・・・・・(略)・・・・・・・・・・・・ <item> <title>RSS 生成対象の n番目 の記事の 題名</title> <link>RSS 生成対象の n番目 の記事の URL</link> <description>RSS 生成対象の n番目 の記事の 概要</description> </item> </channel> </rss>
入力ファイルに
<rss version="0.91">
という文字列が含まれていたら、RSS 0.91 と見なすことにします。
RSS 0.91 のリーダー readRSS_0_91() を やっつけ (^^; で作ると、
以下のようになります(しつこいようですが、念のために書いておきます。以下のコードは、後日、リファクタリングを堪能するため、わざと突っ込みどころのあるコードを書いています。そうは言っても、一応、ちゃんと動かないと話にならないので、動作確認はしてあります)。
int readRSS_0_91( FILE *input, FILE *output, int mode, const char *encoding ) { char buf[BUFSIZ], *p, *q, *r; int ret = 0; char title[BUFSIZ]; char link[BUFSIZ]; char description[BUFSIZ]; char language[BUFSIZ]; int cnt = 0; language[0] = '\0'; while ( ( p = fgets( buf, BUFSIZ - 1, input ) ) != NULL ) { while ( (*p == ' ') || (*p == '\t') ) p++; if ( !strncmp( p, "<title>", 7 ) ) { q = strchr( p + 7, '<' ); if ( q ) { strncpy( title, p + 7, q - (p + 7) ); title[q - (p + 7)] = '\0'; } else { strcpy( title, p + 13 ); while ( ( p = fgets( buf, BUFSIZ - 1, input ) ) != NULL ) { while ( (*p == ' ') || (*p == '\t') ) p++; strcat( title, " " ); strcat( title, p ); if ( ( q = strchr( title, '<' ) ) != NULL ) { *q = '\0'; break; } } } } else if ( !strncmp( p, "<link>", 6 ) ) { q = strchr( p + 6, '<' ); if ( q ) { strncpy( link, p + 6, q - (p + 6) ); link[q - (p + 6)] = '\0'; } } else if ( !strncmp( p, "<description>", 13 ) ) { q = strchr( p + 13, '<' ); if ( q ) { strncpy( description, p + 13, q - (p + 13) ); description[q - (p + 13)] = '\0'; } else { strcpy( description, p + 13 ); while ( ( p = fgets( buf, BUFSIZ - 1, input ) ) != NULL ) { while ( (*p == ' ') || (*p == '\t') ) p++; strcat( description, " " ); strcat( description, p ); if ( ( q = strchr( description, '<' ) ) != NULL ) { *q = '\0'; break; } } } } else if ( !strncmp( p, "<language>", 10 ) ) { q = strchr( p + 10, '<' ); if ( q ) { strncpy( language, p + 10, q - (p + 10) ); language[q - (p + 10)] = '\0'; } } else if ( !strncmp( p, "<item>", 6 ) ) break; } fprintf( output, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD " "HTML 4.01 Transitional//EN\">\n" ); if ( language[0] ) fprintf( output, "<html lang=\"%s\">\n<head>\n", language ); else fprintf( output, "<html>\n<head>\n" ); fprintf( output, "<meta http-equiv=\"Content-Type\" content=\"text/html; " "charset=%s\">\n", encoding ); fprintf( output, "<title>%s</title>\n", title ); fprintf( output, "</head>\n\n<body>\n" ); fprintf( output, "<h1><a href=\"%s\">%s</a></h1>\n", link, title ); fprintf( output, "<h2>%s</h2>\n", description ); while ( ( p = fgets( buf, BUFSIZ - 1, input ) ) != NULL ) { while ( (*p == ' ') || (*p == '\t') ) p++; if ( !strncmp( p, "<item>", 6 ) || (cnt == 0) ) { cnt++; if ( cnt == 1 ) fputs( "<ul>\n", output ); title[0] = '\0'; link[0] = '\0'; description[0] = '\0'; if ( cnt > 1 ) continue; } if ( cnt >= 1 ) { if ( !strncmp( p, "<title>", 7 ) ) { q = strchr( p + 7, '<' ); strncpy( title, p + 7, q - (p + 7) ); title[q - (p + 7)] = '\0'; } else if ( !strncmp( p, "<link>", 6 ) ) { q = strchr( p + 6, '<' ); strncpy( link, p + 6, q - (p + 6) ); link[q - (p + 6)] = '\0'; } else if ( !strncmp( p, "<description>", 13 ) ) { q = strchr( p + 13, '<' ); if ( q && !strncmpi( q, "<![CDATA[", 9 ) ) { p += 9; r = strchr( q, '>' ); if ( r ) { *r = '\0'; while ( *--r == ']' ) *r = '\0'; } q += 9; strcpy( description, q ); } else if ( q ) { strncpy( description, p + 13, q - (p + 13) ); description[q - (p + 13)] = '\0'; } } else if ( !strncmp( p, "</item>", 7 ) ) { if ( title[0] && link[0] && description[0] ) { fprintf( output, "<li><a href=\"%s\">%s</a><br>", link, title, description ); fputs( "</li>\n", output ); title[0] = '\0'; link[0] = '\0'; description[0] = '\0'; } } } } if ( cnt >= 1 ) fputs( "</ul>\n", output ); fprintf( output, "</body>\n</html>\n" ); return ( ret ); }
今回、作成した関数のプロトタイプ宣言をヘッダファイルに追加しておきます。
/* * readRSS * RSS ファイルを元に html ファイルを生成する * written by H.Tsujimura 15 Dec 2003 * * History: * $Log: readRSS.h $ * Revision 1.2 2004/03/17 00:33:35 tsujimura543 * RSS 0.91 対応 * * Revision 1.1 2003/12/15 10:50:51 tsujimura543 * Initial revision * */ #ifndef __READRSS_H__ #define __READRSS_H__ #ifdef __READRSS_C__ #ifndef lint static char *rcs_id_header = "$Header: C:/user/local/src/makeRSS/src/readRSS/RCS/readRSS.h 1.2 2004/03/17 00:33:35 tsujimura543 Exp tsujimura543 $"; #endif #endif /* mode */ #define MODE_NORMAL 0 /* normal html */ #define MODE_I_MODE 1 /* for i-mode */ #define MODE_J_SKY 2 /* for J-SKY */ #define MODE_EZWEB 3 /* for EZweb */ #define MODE_OTHER 0x7F /* for others (L-mode, H", astel) */ /* RSS version */ /* * RSS 0.91 -+------------------------------------------------------------ * +- RSS 1.0 -------------------------------------------------- * +- RSS 0.92 -- RSS 0.93 -+----------------------------------- * +- RSS 2.0 ------------------------ * +- ATOM 0.1 -- ATOM 0.2 -+---------- * +- ATOM 0.3 */ #define VER_UNDEFINED 0 #define VER_RSS_0_91 0x01 #define VER_RSS_0_92 0x12 #define VER_RSS_0_93 0x13 #define VER_RSS_1_00 0x02 #define VER_RSS_2_00 0x14 #define VER_RSS_3_00 0x25 /* 対応しない */ /* ATOM は将来対応(しないかも?) */ #define VER_ATOM_0_1 0x34 #define VER_ATOM_0_2 0x35 #define VER_ATOM_0_3 0x36 int readRSS( FILE *input, FILE *output, int mode ); int readRSS_0_91( FILE *input, FILE *output, int mode, const char *encoding ); int readRSS_1_00( FILE *input, FILE *output, int mode, const char *encoding ); int readRSS_2_00( FILE *input, FILE *output, int mode, const char *encoding ); char *dateString( const char *date, const char *encoding ); char *categoryString( const char *encoding ); #endif /* __READRSS_H__ */
readRSS() の RSS 版数判定部分を以下のように書き換えて、 今回作った readRSS_0_91() を組み込めば OK。
/* RSS の版数を判定し、対応する RSS リーダーを呼び出す */
if ( !strncmp( p, "xmlns=\"http://purl.org/rss/1.0/\"", 32 ) ) {
version = VER_RSS_1_00;
ret = readRSS_1_00( input, output, mode, encoding );
break;
}
if ( !strncmp( p, "<rss version=\"0.91\">", 20 ) ) {
version = VER_RSS_0_91;
ret = readRSS_0_91( input, output, mode, encoding );
break;
}
次回は RSS 2.0 のリーダーを作ってみることにします。
(つづく)


