【連載】

実践! iPhoneアプリ開発

【第7回】RSSリーダの作り方 (3) - XMLをパースする

[2009/03/27 11:55]木下誠 ブックマーク ブックマーク

開発ソフトウェア

前回はRSSフィードをダウンロードするところまで説明した。今回は、ダウンロードしたXMLデータをパースすることについて、説明しよう。

iPhoneのXMLライブラリ

iPhoneは、標準で2種類のXMLをパースするためのライブラリを備える。libxml2とNSXMLParserだ。

libxml2はGnomeプロジェクトで開発された、XMLのパーサライブラリだ。もともとは、GnomeというLinuxディストリビューションの1つに対して開発されたものだが、MITライセンスのもとでソースコードが公開されているため、多くのプラットフォームに移植されている。もちろんMac OS Xにも移植され、それがiPhoneでも使えるようになっている。

libxml2の特徴は、高機能である事だ。まず基本的なXMLパーサ機能として、SAXおよびDOMパーサを提供する。さらに、XMLに関する多くの標準に対応している。たとえば、XML、名前空間、XPath、XPointer、HTML、XInclude、XSLT、XML Schema、Relax NGなどが挙げられる。また、C言語で書かれているため、高速に動作する。APIもC言語で提供される。

NSXMLParserは、Cocoaに含まれるXMLパースのためのクラスだ。SAXパーサ機能を提供する。Cocoaの一部のため、APIはObjective-Cで提供される。そのため、Cocoaアプリケーションとの親和性は非常によい。使いこなすのは簡単だろう。

XMLパースとメモリのフットプリント

さて、このようなXMLライブラリがあることは分かったが、どれを使うべきだろう?ここで考慮しなくてはいけないのは、iPhoneはやはり組み込みデバイスの一種であるということだ。つまり、メモリやCPUといったハードウェアリソースは限られている。ならば、ライブラリの選定を行うときは、パフォーマンスとメモリのフットプリントに気をつけなくてはいけない。

まず一般に、SAXパーサとDOMパーサのメモリのフットプリントを比べると、SAXの方が小さくなる。これは、もともとのパーサの設計思想の違いによるものだ。流れ処理的にパースを行うSAXと、木構造を保持することを目的とするDOMでは、メモリの使用量はもちろん差が出る。

では、iPhoneで実際にDOMパーサを使う事を考えてみる。現在のiPhone 3Gは、搭載されている物理メモリは128MB程度。そのうちiPhone OSが使用するものがあり、ユーザの使用状況によっては音楽を再生していたり、メールやSafariが常駐していたりする。ならば、自分のアプリケーションが使えるメモリ領域は、良くて10MB程度と見積もっておいた方が無難だろう。

そのような状況でXMLのパースを行うのだが、昨今はインターネット上でやりとりされるXMLファイルは肥大化の傾向にある。たとえばRSSは、もともとはWebページの要約を配信するものだった。それがRSSリーダの発展に伴って、記事の全文を入れたり、テキスト形式とHTML形式の両方を加えているものも珍しくない。これにより、数百KBや数MBのRSSフィードも見かけるようになった。

これほどの大きさのものを、DOMでパースするのは、避けておいた方がいいだろう。あっという間にアプリケーションのメモリ領域を食いつぶして、クラッシュしてしまうことが予想される。対象となるXMLファイルが十分に小さい事が保証されるのであれば、問題はない。だがRSSリーダのように、どのようなサイズのファイルが来るのか分からない場合は、DOMパーサの使用は避けたい。

libxml2 vs. NSXMLParser

ならば、libxml2のSAXパーサか、NSXMLParserか、ということになる。実は、この2つを比較するためのサンプルが、iPhone SDKに付属している。XMLPerformanceというサンプルだ。

このサンプルでは、iTunes Storeからトップ300のRSSをダウンロードして、パースする。その際に、使用するXMLライブラリを、libxml2かNSXMLParserかで指定する事ができ、そのパフォーマンスを計測してくれるものだ。

筆者の環境で何回かテストしてみたところ、次のような結果を得た。

ダウンロード パース 合計
NSXMLParser 1.419s 5.525s 7.134s
libxml2 2.520s 2.247s 2.646s

libxml2の方が、NSXMLParserよりも高速な事が分かるだろう。正直、圧倒的とも言える。アプリケーションを使用するときに、十分体感できる差だ。

この差はどこから来るのだろうか。NSXMLParserは、パースを行うバックエンドとしてlibxml2を使っている。従って、パース機能の差ではないだろう。

まず考えられるのが、Objective-C APIによるものだ。NSXMLParserでは、SAX APIの呼び出し時に、引数の文字列を渡すためにNSStringオブジェクトやNSDictionaryオブジェクトを作成している。すべてのタグに対してこの生成を行うのだから、時間のロスは決して小さくない。

もう1つ考えられるのが、パース処理をどの時点から開始するのか、ということだ。先ほどの表をもう一度見てほしい。NSXMLParserの方は合計時間が、ほぼダウンロード時間とパース時間とを足したものになっているのに対して、libxml2の方はそうはなっていない。これは、NSXMLParserはすべてのXMLデータをダウンロードしてからパースを開始するのに対して、libxml2では一部のデータが得られたらすぐにパースを開始しているのだ。そのため、ダウンロード時間と合計時間が、だいたい同じくらいになっている。ユーザにとっても、逐次的に結果が得られるので、心理的負担が軽いだろう。

このような理由で、大きいXMLファイルをパースするときは、libxml2の使用をお勧めする。次回は、libxml2を使ったパースの実際を紹介しよう。

1184
2
【連載】実践! iPhoneアプリ開発 [7] RSSリーダの作り方 (3) - XMLをパースする
前回はRSSフィードをダウンロードするところまで説明した。今回は、ダウンロードしたXMLデータをパースすることについて、説明しよう。
https://news.mynavi.jp/itsearch/2016/02/22/iphone_apps/index_07.jpg
前回はRSSフィードをダウンロードするところまで説明した。今回は、ダウンロードしたXMLデータをパースすることについて、説明しよう。

会員新規登録

初めてご利用の方はこちら

会員登録(無料)

マイナビニュース スペシャルセミナー 講演レポート/当日講演資料 まとめ
人事・経理・総務で役立つ! バックオフィス系ソリューション&解説/事例記事まとめ

一覧はこちら

今注目のIT用語の意味を事典でチェック!

一覧はこちら

ページの先頭に戻る