Swift版RSS Parser


RSS Readerを作成中です。そのための第一歩として、Swift版RSS Parserを作成しました。

実行環境は、MacOSX El Capitan、Xcode 7.1.1です。

# 概要
[NSXMLParser](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSXMLParser_Class/)を使ってRSS Feed(XML)をパースします。RSS Feedのitem要素をDictionaryに変換して配列に格納しています。

# 使い方
playgroundファイルを、[GitHub](https://github.com/unokun/rss-feed-parser)から取得してXcode7でオープンください。

Consoleに以下の内容が出力されます。

```
http://weather.livedoor.com/forecast/rss/area/330010.xml
count: 7
13
title ---> [ 28日（土）の天気 ] 岡山 - 晴時々曇 - 最高気温13℃ - 11月28日(土)
category ---> 天気予報
...
```

RSSフィードを変更する場合には、108行目を修正します。

```swift
let URL = NSURL(string: "http://weather.livedoor.com/forecast/rss/area/330010.xml")
```

出力を変更する場合には122行のコードを修正します。

```swift
    print("count: \(parser.items.count)")
    for item in parser.items {
        print(item.count)
        for (key, value) in item {
            print("\(key) ---> \(value)")
        }
    }
```

取得しているRSSフィードの内容を知りたい場合には、117行目のコメントアウトを外します。

```swift
    //    print(NSString(data: data!, encoding: NSUTF8StringEncoding))
```

# 実装
## RSSフィード
今回処理対象にしている天気予報のRSSフィードです。

```xml
<rss version=\"2.0\" xmlns:ldWeather=\"http://weather.livedoor.com/ns/rss/2.0\">
<channel>
...
<item>
  <title>[ 28日（土）の天気 ] 岡山 - 晴時々曇 - 最高気温13℃ - 11月28日(土)</title>
  <link>http://weather.livedoor.com/area/forecast/330010?r=rss20151128</link>
  <category>天気予報</category>
  <day>Saturday</day>
  <image>
    <title>晴時々曇</title>
    <link>http://weather.livedoor.com/area/forecast/330010?r=rss20151128</link>
    <url>http://weather.livedoor.com/img/icon/2.gif</url>
    <width>50</width>
    <height>31</height>
  </image>
  <description>28日（土）の天気は晴時々曇、最高気温は13℃ 最低気温は3℃でしょう。</description>
  <pubDate>Wed, 25 Nov 2015 17:00:00 +0900</pubDate>
</item>
...
</channel>
```
これを、辞書の配列データに変換します。item以下を辞書に変換し配列に格納します。

```swift
var items = Array<Dictionary<String, String>>()
```

辞書のデータイメージです。image要素の子要素は、キーにimage_というprefixを付け、辞書に追加しています。

```swift
{
  "title":"[ 28日（土）の天気 ] 岡山 - 晴時々曇 - 最高気温13℃ - 11月28日(土)",
   ...,
  "image_title":"晴時々曇",
  "image_link":"http://weather.livedoor.com/area/forecast/330010?r=rss20151128",
  ...
} 
```

## RSSフィード取得
[NSURLSession.dataTaskWithRequest](https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSURLSession_class/)を使っています。

使い方は、[iOS - NSURLSession経由でHTTP requestを投げるサンプルコード Swift版 - Qiita](http://qiita.com/nyamage/items/48d5ee30869daaf70f7f)を参考にしました。また、XCode7での変更点について、[Swift2.0 - Xcode 7.1で気がついたPlaygroundの変更点 - Qiita](http://qiita.com/koishi/items/e78f8b852d5f7ae8d125)を参考にしました。

```swift
let URL = NSURL(string: "http://weather.livedoor.com/forecast/rss/area/330010.xml")
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let request = NSURLRequest(URL: URL!)


let task = session.dataTaskWithRequest(request, completionHandler: {
    (data, resp, err) in
    // 取得したデータの処理を記述する
})
task.resume()
```

## XMLパース
[NSXMLParser](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSXMLParser_Class/)を使っています。NSXMLParserはSAXベースのXML Parserです。[NSXMLParserDelegate](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSXMLParserDelegate_Protocol/index.html#//apple_ref/doc/uid/TP40008632)のメソッドをオーバーライドして必要なデータを処理します。
今回は、Element開始/終了とテキストを処理しました。

オーバーライドしたメソッドです。

|処理|関数|
|:---|:---|
|Element開始|parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String])|
|Element終了|parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?)|
|Text|parser(parser: NSXMLParser, foundCharacters string: String)|

処理内容です。

|処理|処理内容|
|:---|:---|
|Element開始|辞書を作成します。|
|Element終了|辞書のキー（要素名）にテキストを追加します。item要素の場合には、現在処理中の辞書を配列に追加します。|
|Text|テキストを結合します。テキスト要素は、複数回呼ばれるので文字列結合する必要があります。|

image要素は、要素名(image_)をキーに追加しています。この処理をするためにimage要素処理中フラグ(processingImage)を使っています。


## 参考資料
* [NSXMLParser Class Reference](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSXMLParser_Class/)
* [NSXMLParserDelegate Protocol Reference](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSXMLParserDelegate_Protocol/index.html#//apple_ref/doc/uid/TP40008632)
* [NSURLSession Class Reference](https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSURLSession_class/)
* [iOS - NSURLSession経由でHTTP requestを投げるサンプルコード Swift版 - Qiita](http://qiita.com/nyamage/items/48d5ee30869daaf70f7f)
* [Swift2.0 - Xcode 7.1で気がついたPlaygroundの変更点 - Qiita](http://qiita.com/koishi/items/e78f8b852d5f7ae8d125)