iPhoneアプリ作るためにXMLのパースをしたくて勉強
iPhoneアプリを作ってみたいと思い、手探りで勉強をはじめだしたところ。
とりあえずRSSのパースからやってみようと思ったら速攻でハマったのでメモメモ。
前提
- iPhone でXMLのDOM解析を行う - 謎言語使いの徒然に従って、GDataXMLNodeというのを使ってXMLのパースをする
- とりあえずローカルに実際にあるフィードのRDFファイルを用意してそれを読み込んでNSLogでタイトルだけでも出してみる
ハマった所
- そのままやったのに空データが返って来てムキャー!ってなった
結論
- ハマった理由はnamespaceでした
- ちゃんとnamespaceを考慮しましょう
- iPhone でXMLのDOM解析を行う - 謎言語使いの徒然の通りにやればXMLのパースはできます
- コピペだけでできちゃうなんて嬉しすぎるね!
- 【iPhone】KissXMLで快適パース生活 | iPhoneアプリ開発で稼げるのかを見てみると他にも色々XMLのパース用ライブラリはあるのですね
- ハマった瞬間にこの記事見つけたら確実にこっちに流れてたな
ハマった流れ
- まずはiPhone でXMLのDOM解析を行う - 謎言語使いの徒然の通りにサンプルコードまでコピー
- サンプルのXMLをRDFにしたので、とりあえず<title>だけ取ろうとXPath部分を以下のように変更
NSArray* titleList = [rootNode nodesForXPath:@"//title" error:&error]; NSLog(@"%@", titleList); // titleリストが出てくれますように。
- でもなぜか以下のようなログになってタイトルが取ってこられない
2010-01-15 22:46:10.496 samplePrj[43007:20b] ( )
- 「そういえば昔何かでパースしようとした時にnamespaceでハマったな。それかな?」と思い、「GDataXMLNode nodeForXPath」でググった
- そしたらソースにたどり着きまして、以下のようなオーバーロードのメソッドを見つける
- (NSArray *)nodesForXPath:(NSString *)xpath
namespaces:(NSDictionary *)namespaces
error:(NSError **)error {
- で、ここでNSDictionaryがよくわからなくて、namespacesの指定方法がわからず、またハマる。
- (結局NSDictionaryはハッシュみたいなものなかな?多分。)
- そしたら【iPhone】KissXMLで快適パース生活 | iPhoneアプリ開発で稼げるのかでいい感じの内容を見つける
Google Readerからのレスポンスを見てみるとルートのfeedエレメントにはnamespaceをたくさん指定しています。こんな感じです。
<feed xmlns:idx="urn:atom-extension:indexing" xmlns:gr="http://www.google.com/schemas/reader/atom/" xmlns:media="http://search.yahoo.com/mrss/" xmlns="http://www.w3.org/2005/Atom" idx:index="no">なのでこれらをルートエレメントに教えてやる。
[root addNamespace:[DDXMLNode namespaceWithName:@"idx" stringValue:@"urn:atom-extension:indexing"]]; [root addNamespace:[DDXMLNode namespaceWithName:@"gr" stringValue:@"http://www.google.com/schemas/reader/atom/"]]; [root addNamespace:[DDXMLNode namespaceWithName:@"media" stringValue:@"http://search.yahoo.com/mrss/"]]; [root addNamespace:[DDXMLNode namespaceWithName:@"foo" stringValue:@"http://www.w3.org/2005/Atom"]];これで取り出す準備完了。defaultのnamespaceであるhttp://www.w3.org/2005/Atomには適当にfooという名前を付けた。
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: @"http://purl.org/rss/1.0/", @"foo", @"http://www.w3.org/1999/02/22-rdf-syntax-ns#", @"rdf", @"http://purl.org/rss/1.0/modules/taxonomy/", @"taxo", @"http://purl.org/rss/1.0/modules/syndication/", @"sy", @"http://purl.org/dc/elements/1.1/", @"dc", nil]; NSArray* titleList = [rootNode nodesForXPath:@"//foo:title" namespaces:dict error:&error]; NSLog(@"%@", titleList); // titleリストが出てくれますように。
- そしたら!そしたら!
2010-01-15 23:47:42.284 samplePrj[43800:20b] 「著作権法改正」でもWinnyは相変わらず、逮捕続きのShareは減少 〜 ネットエージェント調べ:Enterprise:RBB TODAY (ブロードバンド情報サイト) 2010/01/15 2010-01-15 23:47:42.284 samplePrj[43800:20b] 犬も歩けば猫も歩く。: 松本人志が出演。「のだめカンタービレ」 2010-01-15 23:47:42.313 samplePrj[43800:20b] YouTube - 豊田エリー ♪ ぱなしのはなし
- うひょー!!!!!やったぜ!タイトルが取得できた!!!!!
ということで嬉しくなったので今日はここまでにしました。あとはparseFeed的なメソッドか何かを作ろうと思います。