技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

iPhone でXMLのDOM解析を行う

デフォルトの NSXMLPerser がシーケンスアクセスしかできなくてとても扱いづらい。
かといって、根っこの libxml2 は高性能で早くて DOM 使えるのにドキュメントが腐ってて扱いにくい。
で、探して見っけたのがこれ

http://code.google.com/p/gdata-objectivec-client/

使い方は、以下の通り。

  1. Frameworks を右クリック、追加、既存のフレームワーク
  2. /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/usr/lib/libxml2.2.dylib をさくっと選択。
  3. ターゲットのバイナリをライブラリにリンクに、libxml2.dylib をドロップ。
  4. ターゲットを開いて、ビルドタブを開き、「リンク」「他のリンカフラグ」に「-lxml2」を追加。
  5. そのまま、「検索パス」「ヘッダ検索パス」に「/usr/include/libxml2」と「/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.sdk/usr/include/libxml2」を追加。
  6. http://code.google.com/p/gdata-objectivec-client/ このへんからライブラリ落としてきて解凍
  7. GDataTargetNamespace.h, GDataDefines.h, GDataXMLNode.h, GDataXMLNode.m をプロジェクトにコピー

これでとりあえず準備完了。

以下サンプル

sample.xml

<users>
    <user id="0">
        <name>azalea</name>
        <email>azalea@azalea.net</email>
        <address country="Japan">Hokkaido</address>
    </user>
    <user id="1">
        <name>Baka.K.El.Doglla</name>
        <email>unknown@unknown.net</email>
        <address country="Doglla">Doglla</address>
    </user>
</users>

で、これから名前だけ取り出す場合。

#import "GDataXMLNode.h"

- (void)applicationDidFinishLaunching:(UIApplication *)application {
	
	// load xml file as text
	NSString* path = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"xml"];
	NSString* fileText = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
	NSLog(@"path:%d , fileText:%d",[path retainCount],[fileText retainCount]);
	
	// parse text as xml
	NSError* error;
	GDataXMLDocument* document = [[GDataXMLDocument alloc] initWithXMLString:fileText options:0 error:&error];
	GDataXMLElement *rootNode = [document rootElement];
	
	// get user names by xpath
	int count = 0;
	NSArray* userList = [rootNode nodesForXPath:@"//users/user/name" error:&error];
	for(GDataXMLNode* node in userList) {
		NSLog([node stringValue]);
	}
	
	// Configure and show the window
	[window addSubview:[navigationController view]];
	[window makeKeyAndVisible];
	[document release];
}

これでかなりマシになった。
ベンチマークしてないけど、NSXMLParser とそう違わないレスポンス出るんじゃないだろうか?