Hatena::Groupiphone-dev

haoyayoi Dev Style このページをアンテナに追加 RSSフィード

2009-08-23

SAXパーサでRSSやHTMLを解析する

21:30 | SAXパーサでRSSやHTMLを解析する - haoyayoi Dev Style を含むブックマーク はてなブックマーク - SAXパーサでRSSやHTMLを解析する - haoyayoi Dev Style SAXパーサでRSSやHTMLを解析する - haoyayoi Dev Style のブックマークコメント

XMLHTMLを内部で解析できればアプリ作成でも幅が広くなると思い、只管パース用のクラス作成に没頭してました。マイコミジャーナルの記事にて各々の関数の説明が、allnightappsさんの記事にて大まかな流れがだいたい汲み取れると思います。

ここではSAXハンドラの定義について触れてみることにします。

参考リンク

libxmlの指定

「他のリンカフラグ」に-lxml2を指定し、「ヘッダ検索パス」にlibxml2へのパスを指定します。パスはバージョンに合わせてください。

/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr/include/libxml2

ヘッダへの追記

#import <libxml/HTMLparser.h>

SAXハンドラの定義

パースの際に必要なメソッドの定義など行います。SAXパーサのハンドラにはいくつもの要素がありますが、必要なものだけを定義でも問題ありません。今回は開始タグ、閉じタグ、タギングされたテキストの判定を行っています。

SAXパーサハンドラにて指定した関数が、クラスメソッドへ値を渡していく流れとなっています。

//クラスメソッド
@interface Parser (private)
- (void)startElementName:(const xmlChar*)name attributes:(const xmlChar**)attributes;//開始タグ用
- (void)endElementName:(const xmlChar*)name;//閉じタグ用
- (void)character:(const xmlChar*)ch length:(int)length;//タギングテキスト用
@end

//SAXパーサ用関数の定義

//開始タグ判定時に実行される関数 StartElementSAXHandle
//引数:: ctx = ハンドラ、name = タグ名、atts = 要素(配列)
static void StartElementSAXHandle(void *ctx, 	const xmlChar * name,	const xmlChar **atts) {
    [(Parser*)ctx startElementName:name attributes:atts]; //定義した開始タグ用メソッドに渡す
}

//閉じタグ判定に実行される関数 EndElementSAXHandle
//引数:: ctx = ハンドラ、name = タグ名
static void EndElementSAXHandle(	void *ctx, const xmlChar *name) {
    [(Parser*)ctx endElementName:name];//定義した閉じタグ用メソッドに渡す
}

//タギングされているテキスト判定時に実行される関数 CharacterElementSAXHandle
//引数:: ctx = ハンドラ、ch = テキスト、len = テキストの長さ
static void CharacterElementSAXHandle( void *ctx, const xmlChar *ch, int len ) {
    [(Parser*)ctx character:ch length:len];//定義したタギングテキスト用メソッドに渡す
}

//ハンドラの定義(4つしか定義してませんが、これ以外にも複数存在します)
static xmlSAXHandler gSAXHandler = {
.initialized    = XML_SAX2_MAGIC,
.startElement   = StartElementSAXHandle, //要素開始時に実行される関数を指定
.endElement     = EndElementSAXHandle, //要素終了時に実行される関数を指定
.characters     = CharacterElementSAXHandle //テキスト判定時に実行される関数を指定
};

パースの流れ方

<data>test</data>

上記のようなxmlの場合、dataの開始タグが判定された際にStartElementSAXHandleが実行されます。その後、タギングされているテキストである「test」が判定されて、CharacterElementSAXHandleが実行されます。最後に閉じタグにてEndElementSAXHandleが実行となります。

f:id:hao_yayoi:20090823213036p:image

データ保持

SAXパーサでは、データを取得しつつパースが走るため、逐一パースされる度にデータを保存する必要があります。よって、テキストを保持する場合にはNSMutableStringなどによって追加する形になります。以下はタギングされたテキストを保持する例です。

- (void)character:(const xmlChar*)ch length:(int)length {
	NSString* _strpar = [[NSString alloc] initWithBytes:ch length:length encoding:NSUTF8StringEncoding];
	[_mutableStr appendString:_strpar];
	[_strpar release];
}