iPhone でXMLのDOM解析を行う
デフォルトの NSXMLPerser がシーケンスアクセスしかできなくてとても扱いづらい。
かといって、根っこの libxml2 は高性能で早くて DOM 使えるのにドキュメントが腐ってて扱いにくい。
で、探して見っけたのがこれ
http://code.google.com/p/gdata-objectivec-client/
使い方は、以下の通り。
- Frameworks を右クリック、追加、既存のフレームワーク
- /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/usr/lib/libxml2.2.dylib をさくっと選択。
- ターゲットのバイナリをライブラリにリンクに、libxml2.dylib をドロップ。
- ターゲットを開いて、ビルドタブを開き、「リンク」「他のリンカフラグ」に「-lxml2」を追加。
- そのまま、「検索パス」「ヘッダ検索パス」に「/usr/include/libxml2」と「/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.sdk/usr/include/libxml2」を追加。
- http://code.google.com/p/gdata-objectivec-client/ このへんからライブラリ落としてきて解凍
- 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 とそう違わないレスポンス出るんじゃないだろうか?