Edited at

Swift でXMLパースしてみました。

More than 1 year has passed since last update.


Swift でXMLパース


Overview

swiftでXMLパースをしてみました。

OSSでは下記を見つけました

上記2点以外にもXMLパーサーは存在しているかもしれませんが、

今回はこの2点を列挙させていただきました。

実際にパースしてみたのは drmohundro/SWXMLHash になります。

yahoojapanのXMLパーサーも影響を受けたそうですので、こちらにしてみました。


Use it


Cocoapods

To install CocoaPods, run:

$ gem install cocoapods


Podfile

platform :ios, '10.0'

use_frameworks!

target 'YOUR_TARGET_NAME' do
pod 'SWXMLHash', '~> 4.0.0'
end


Podfileに上記を記述し、下記を実行します。


$ pod install

通信クラスには下記を使います

keisukeYamagishi/HttpSession

TCP / IP based HTTP communication can be simplified

なのでPodfileは下記のようにします。


Podfile

platform :ios, '10.0'

use_frameworks!

target 'YOUR_TARGET_NAME' do
pod 'SWXMLHash', '~> 4.0.0'
pod 'HttpSession'
end



$ pod install

下記のようなXMLをパースする場合の使い方になります。


<rest order="0">
<id>6363054</id>
<update_date>2017-12-10 05:04:30</update_date>
<name>餃子の安亭 新宿店</name>
<name_kana>ギョウザノアンテイシンジュクテン</name_kana>
<latitude>35.690078</latitude>
<longitude>139.702786</longitude>
<category>餃子</category>
<url>
https://r.gnavi.co.jp/efk1099b0000/?ak=Dil4xinerVDUdo2%2BMpaU4uwlSorYa1jve%2BRSBbdUIAQ%3D
</url>
<url_mobile>
http://mobile.gnavi.co.jp/shop/6363054/?ak=Dil4xinerVDUdo2%2BMpaU4uwlSorYa1jve%2BRSBbdUIAQ%3D
</url_mobile>
<coupon_url>
<pc/>
<mobile/>
</coupon_url>
<image_url>
<shop_image1/>
<shop_image2/>
<qrcode>https://c-r.gnst.jp/tool/qr/?id=6363054&q=6</qrcode>
</image_url>
<address>〒160-0023 東京都新宿区西新宿1-2-1 ファイブKビル2F</address>
<tel>03-5323-8228</tel>
<tel_sub/>
<fax/>
<opentime>
11:30~15:00(L.O.14:45)(平日)、17:00~23:30(L.O.23:00)(平日)<BR>土・日・祝日 11:30~23:30(L.O.23:30)(ランチ~14:30)
</opentime>
<holiday/>
<access>
<line>都営大江戸線(環状部)</line>
<station>新宿西口駅</station>
<station_exit>D3口</station_exit>
<walk>徒歩1</walk>
<note/>
</access>
<parking_lots/>
<pr>
<pr_short/>
<pr_long/>
</pr>
<code>
<areacode>AREA110</areacode>
<areaname>関東</areaname>
<prefcode>PREF13</prefcode>
<prefname>東京都</prefname>
<areacode_s>AREAS2120</areacode_s>
<areaname_s>新宿西口・都庁前</areaname_s>
<category_code_l order="0">RSFST14000</category_code_l>
<category_name_l order="0">中華</category_name_l>
<category_code_s order="0">RSFST14008</category_code_s>
<category_name_s order="0">餃子</category_name_s>
<category_code_l order="1"/>
<category_name_l order="1"/>
<category_code_s order="1"/>
<category_name_s order="1"/>
</code>
<budget/>
<party/>
<lunch/>
<credit_card/>
<e_money/>
<flags>
<mobile_site>1</mobile_site>
<mobile_coupon>0</mobile_coupon>
<pc_coupon>0</pc_coupon>
</flags>
</rest>

パースしたいxmlの構造を下記のようにコーディングします。

これを配列として扱ってやるとやってくれます。


public struct Rest: XMLIndexerDeserializable {
var name: String = ""
var latitude: String = ""
var longitude: String = ""
var address: String = ""
var url: String = ""
init(name: String, latitude:String, longitude: String, address:String, url:String){
self.name = name
self.latitude = latitude
self.longitude = longitude
self.address = address
self.url = url
}
public static func deserialize(_ node: XMLIndexer) throws -> Rest {
return try Rest (
name: node["name"].value(),
latitude: node["latitude"].value(),
longitude: node["longitude"].value(),
address: node["address"].value(),
url: node["url"].value()
)
}
}

let r: [Rest] = try xml["response"]["rest"].value()

全体像はこんな感じです。


//
// ViewController.swift
// DEMO
//
// Created by Shichimitoucarashi on 2018/05/06.
// Copyright © 2018年 keisuke yamagishi. All rights reserved.
///Users/keisukeyamagishi/Code/GAME/DEMO/DEMO/ViewController.swift:42:32: Argument passed to call that takes no arguments

import UIKit
import HttpSession
import SWXMLHash

public struct Rest: XMLIndexerDeserializable {
var name: String = ""
var latitude: String = ""
var longitude: String = ""
var address: String = ""
var url: String = ""
init(name: String, latitude:String, longitude: String, address:String, url:String){
self.name = name
self.latitude = latitude
self.longitude = longitude
self.address = address
self.url = url
}
public static func deserialize(_ node: XMLIndexer) throws -> Rest {
return try Rest (
name: node["name"].value(),
latitude: node["latitude"].value(),
longitude: node["longitude"].value(),
address: node["address"].value(),
url: node["url"].value()
)
}
}

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

Http(url:"https://api.gnavi.co.jp/RestSearchAPI/20150630/?keyid=ed0508a689013e2c064187189fc3c568&latitude=35.6900488&longitude=139.7028957&", method: .get)
.session { (data, responce, error) in

do{
let xml = SWXMLHash.parse(data!)

let r: [Rest] = try xml["response"]["rest"].value()
print (r)
}catch{

}

}
// Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

}