iOS のXML 取得、解析処理には基本的ないくつかの処理があります。
XML の処理方式として、
- SAX
- DOM
イベント駆動で行うXML解析
インターフェース指向で、木構造として扱う方式
があり、iOSでは、
- NSXML(標準, SAX, Objective-C)
- Libxml(標準, SAX, C言語)
- TouchXML, KissXML (外部ライブラリ、DOM)
など、あるのですが、イベントを自分で記述したり、解析のためにオブジェクトをたどったりと、結構めんどうです。それを簡単にする方法があったのでご紹介します。
XMLは面倒なのですが、それに比べて、JSON は、一行で、
[cc lang=”ObjC”]
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData: data options: nil error:nil];
[/cc]
と、一行ですんでしまいます。ちなみに、これは、iOS5 から使えるようになった、Apple 標準SDKのJSONシリアライザです。これがあれば、外部ライブラリを読み込む必要が無くなりますね。これでデータを解析して、NSDictionaryに書き込んでくれます。階層化、配列の対応なども出来ます。これと同じ事がXMLでも出来ないかと思って探してみたら、見つかりました。
Insert-Witty-Name/XML-to-NSDictionary – GitHub こちらです。
これだと,この関数の中で、一通りの処理を行って、JSONの用に、NSDictionaryで返してくれます。自分で各コードはしたのようになります。
[cc lang=”ObjC”]
-(void) receiveInfoWithCompletedBlock:(dispatch_block_t)block errorBlock:(dispatch_block_t)errorBlock{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSURL *url = [NSURL URLWithString:@”http://your.url.com/test.xml”];
ASIHTTPRequest *request;
NSError *err;
request = [[ASIHTTPRequest alloc] initWithURL:url];
[request startSynchronous];
err = [request error];
if (err) {
dispatch_sync(dispatch_get_main_queue(), errorBlock);
return ;
}
dicInfo = [XMLReader dictionaryForXMLData:request.responseData error:&err];
dispatch_sync(dispatch_get_main_queue(), block);
});
}
[/cc]
実際にXMLを解析しているのは、
[cc lang=”ObjC”] dicInfo = [XMLReader dictionaryForXMLData:request.responseData error:&err];
[/cc]
の一行ですね。後のコードは、GCD と Blocks を使って、動作がカクカクならないようにしています。GCD、Blocksに関しては、
に詳しく説明されていますのでオススメです。Blocksを使っていて嬉しいのは、将来こうして欲しいという事を、事前に書いておくことが出来るという事です。これまでの手続き型プログラミングは、その時に何をするかしか書けないのですが、Blocks、GCDによって、将来こういう状況が来たらこういう処理をしてねという事を登録出来る訳ですね。関数型言語に共通するものがありますね。
ちなみに、この関数を読んでいる処理では、
[cc lang=”ObjC”]
[self showDiskMessageWithMessage:@”最新の情報を取得中…”];
[dataObject receivePriceInfoWithCompletedBlock:^{
[self clearDiskMessage];
[self.mainViewController informationReceived:self];
} errorBlock:^{
[self clearDiskMessage];
[self.mainViewController informationReceived:self];
}];
[/cc]
の用に書いていて、ディスクメッセージを表示するコードを書いたすぐ後に、
終わったらこれをしといてね
という事を記述しておくことが出来ます。これによって、コードの視認性が高まりますね。今までは、終わったときの処理に関しては、
- アクションを登録しておく @selector()
- Delegate を作成して、終了関数を呼び出す
などの処理が必要でしたが、それを一気に書くことが出来る訳です。
話が脱線しましたが、このように、XMLも、JSONの用に扱うことによって、使い慣れた NSDictionary, NSArray でデータを管理出来ます。そして、小階層にアクセスするときも、NSDictionary の KeyPath の機能を使って,
[cc lang=”ObjC”]
arrayBook = [dicInfo valueForKeyPath:@”Root.Books.Book”];
[/cc]
というように、小階層を直接文字列で指定して、扱うことが出来ます。
デメリットとして、この方法は、すべてのデータを読み込んで、すべてのデータの処理を行うので、データの量が大きい時に、前半だけ読んで、テーブルに反映する事などが出来ません。それで、大きすぎないデータの時に限られるかもしれません。凄く大きなデータの時は、Libxml で、読みながらデータを作成していくことにより、スピードとレスポンスを保てるので、オススメです。
「iOSのXML解析をJSONみたいに簡単に出来る XML Reader が便利」への1件のフィードバック