Swift學習筆記(2)網路資料交換格式(XML,JSON)解析 [iOS實戰 入門與提高卷]

究極死胖獸發表於2016-05-17

Swift學習筆記(2)網路資料交換格式(XML,JSON)解析

參考書籍及資源:iOS實戰 入門與提高卷 關東昇 參考書籍地址

  • 用NSXML來解析XML文件
  • 用TBXML來解析XML文件
  • 用NSJSONSerialization來解析JSON文件

目錄


用NSXML來解析XML文件

NSXML是iOS SDK自帶的,也是蘋果預設的解析框架,框架的核心是NSXMLParser和它的委託協議NSXMLParserDelegate。

示例文件Notes.xml

<?xml version="1.0" encoding="UTF-8"?>
<Notes>
  <Note id="1">
    <CDate>2014-12-21</CDate>
    <Content>早上8點鐘到公司</Content>
    <UserID>tony</UserID>
  </Note>
  <Note id="2">
    <CDate>2014-12-22</CDate>
    <Content>釋出iOSBook1</Content>
    <UserID>tony</UserID>
  </Note>
  <Note id="3">
    <CDate>2014-12-23</CDate>
    <Content>釋出iOSBook2</Content>
    <UserID>tony</UserID>
  </Note>
  <Note id="4">
    <CDate>2014-12-24</CDate>
    <Content>釋出iOSBook3</Content>
    <UserID>tony</UserID>
  </Note>
  <Note id="5">
    <CDate>2014-12-25</CDate>
    <Content>釋出2016奧運會應用iPhone版本</Content>
    <UserID>tony</UserID>
  </Note>
  <Note id="6">
    <CDate>2014-12-26</CDate>
    <Content>釋出2016奧運會應用iPad版本</Content>
    <UserID>tony</UserID>
  </Note>
</Notes>

建立XMLParser類

import Foundation

class XMLParser: NSObject , NSXMLParserDelegate {

    private var notes:NSMutableArray! = []
    private var currentTagName:String!

    func startParse(){
        NSLog("start parse")

        let path=NSBundle.mainBundle().pathForResource("Notes", ofType: "xml")!
        let url=NSURL(fileURLWithPath: path)

        //開始解析
        let parser=NSXMLParser(contentsOfURL: url)!
        parser.delegate=self
        parser.parse()
    }

    //文件開始時觸發
    func parserDidStartDocument(parser: NSXMLParser) {
        self.notes=NSMutableArray()
    }

    //文件出錯時觸發
    func parser(parser: NSXMLParser, parseErrorOccurred parseError: NSError) {
        NSLog("%@", parseError)
    }

    //遇到一個開始標籤時觸發,其中namespaceURI是名稱空間,qualifiedName是限定名,attributes是字典屬性集合
    func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
        self.currentTagName=elementName
        if self.currentTagName == "Note"{
            let id=attributeDict["id"]! as NSString
            let dict=NSMutableDictionary()
            dict.setObject(id, forKey: "id")
            self.notes.addObject(dict)
        }
    }

    //遇到字串時觸發
    func parser(parser: NSXMLParser, foundCharacters string: String) {
    //去除空格和回車
        let s1 = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
        if s1 == ""{
            return
        }
        let dict = self.notes.lastObject as! NSMutableDictionary
        if (self.currentTagName == "CDate"){
            dict.setObject(string, forKey: "CDate")
        }
        if (self.currentTagName == "Content"){
            dict.setObject(string, forKey: "Content")
        }
        if (self.currentTagName == "UserID"){
            dict.setObject(string, forKey: "UserID")
        }
    }

    //遇到結束標籤時觸發
    func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        self.currentTagName=nil
    }

    //文件結束時觸發
    func parserDidEndDocument(parser: NSXMLParser) {
        NSLog("end parse")
        NSLog("\(notes)")
    }
}

呼叫與執行結果

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let parser=XMLParser()
        parser.startParse()
    }
2016-05-17 12:03:42.836 XMLTest[61377:445073] start parse
2016-05-17 12:03:42.852 XMLTest[61377:445073] end parse
2016-05-17 12:03:42.853 XMLTest[61377:445073] (
        {
        CDate = "2014-12-21";
        Content = "\U65e9\U4e0a8\U70b9\U949f\U5230\U516c\U53f8";
        UserID = tony;
        id = 1;
    },
        {
        CDate = "2014-12-22";
        Content = "\U53d1\U5e03iOSBook1";
        UserID = tony;
        id = 2;
    },
        {
        CDate = "2014-12-23";
        Content = "\U53d1\U5e03iOSBook2";
        UserID = tony;
        id = 3;
    },
        {
        CDate = "2014-12-24";
        Content = "\U53d1\U5e03iOSBook3";
        UserID = tony;
        id = 4;
    },
        {
        CDate = "2014-12-25";
        Content = "\U53d1\U5e032016\U5965\U8fd0\U4f1a\U5e94\U7528iPhone\U7248\U672c";
        UserID = tony;
        id = 5;
    },
        {
        CDate = "2014-12-26";
        Content = "\U53d1\U5e032016\U5965\U8fd0\U4f1a\U5e94\U7528iPad\U7248\U672c";
        UserID = tony;
        id = 6;
    }
)

用TBXML來解析XML文件

TBXML是第三方框架,使用起來比NSXML更簡單。

準備工作

TBXML下載地址

下載完成後將TBXML-Headers和TBXML-Code資料夾新增到工程中,並新增以下Framewok和庫
這裡寫圖片描述

在Xcode6以後的版本,需要建立PrefixHeader.pch檔案
這裡寫圖片描述

並選擇TARGETS->工程名->Buil Setting->Apple LLVM x.x Language ->Prefix Header,輸入PrefixHeader.pch
這裡寫圖片描述

在PrefixHeader.pch中新增以下程式碼

#import <Foundation/Foundation.h>
#define ARC_ENABLED

在橋接標頭檔案中新增以下程式碼(關於橋接標頭檔案請參考Swift和Objective-C的混編)

#import <Foundation/Foundation.h>
#import "TBXML.h"

建立XMLParser類

import Foundation

class XMLParser: NSObject {

    private var notes:NSMutableArray! = []

    func startParse(){
        NSLog("start parse")

        self.notes=NSMutableArray()
        let tbxml=(try? TBXML(XMLFile: "Notes.xml",error:()))!
        //獲取XML文件根元素
        let root=tbxml.rootXMLElement

        if root != nil{
            //查詢root元素下的Note元素
            var noteElement=TBXML.childElementNamed("Note", parentElement: root)

            while noteElement != nil{
                let dict=NSMutableDictionary()

                //查詢Note元素下的CDate元素
                let CDateElemet=TBXML.childElementNamed("CDate", parentElement: noteElement)
                if CDateElemet != nil{
                    let CDate=TBXML.textForElement(CDateElemet)
                    dict.setValue(CDate, forKey: "CDate")
                }

                //查詢Note元素下的Content元素
                let ContentElemet=TBXML.childElementNamed("Content", parentElement: noteElement)
                if ContentElemet != nil{
                    let Content=TBXML.textForElement(ContentElemet)
                    dict.setValue(Content, forKey: "Content")
                }

                //查詢Note元素下的UserID元素
                let UserIDElemet=TBXML.childElementNamed("UserID", parentElement: noteElement)
                if UserIDElemet != nil{
                    let UserID=TBXML.textForElement(UserIDElemet)
                    dict.setValue(UserID, forKey: "UserID")
                }

                //獲取Note元素的id屬性值
                let id=TBXML.valueOfAttributeNamed("id", forElement: noteElement)
                dict.setValue(id, forKey: "id")

                self.notes.addObject(dict)
                //獲取同層的下一個Note元素
                noteElement=TBXML.nextSiblingNamed("Note", searchFromElement: noteElement)
            }
        }

        NSLog("end parse")
        NSLog("\(notes)")
        self.notes=nil
    }

}

呼叫與執行結果

同上

用NSJSONSerialization來解析JSON文件

NSJSONSerialization是iOS 5之後蘋果提供的API。

示例文件 Notes.data

{"ResultCode":0,"Record":[
{"ID":"1","CDate":"2014-12-23","Content":"釋出iOSBook0","UserID":"tony"},
{"ID":"2","CDate":"2014-12-24","Content":"釋出iOSBook1","UserID":"tony"},
{"ID":"3","CDate":"2014-12-25","Content":"釋出iOSBook2","UserID":"tony"},
{"ID":"4","CDate":"2014-12-26","Content":"釋出iOSBook3","UserID":"tony"},
{"ID":"5","CDate":"2014-12-27","Content":"釋出iOSBook4","UserID":"tony"},
{"ID":"6","CDate":"2014-12-28","Content":"釋出iOSBook5","UserID":"tony"},
{"ID":"7","CDate":"2014-12-29","Content":"釋出iOSBook6","UserID":"tony"},
{"ID":"8","CDate":"2014-12-30","Content":"釋出iOSBook7","UserID":"tony"},
{"ID":"9","CDate":"2014-12-31","Content":"釋出iOSBook8","UserID":"tony"},
{"ID":"10","CDate":"2014-12-32","Content":"釋出iOSBook9","UserID":"tony"},
{"ID":"11","CDate":"2014-12-33","Content":"釋出iOSBook10","UserID":"tony"},
{"ID":"12","CDate":"2014-12-34","Content":"釋出iOSBook11","UserID":"tony"},
{"ID":"13","CDate":"2014-12-35","Content":"釋出iOSBook12","UserID":"tony"},
{"ID":"14","CDate":"2014-12-36","Content":"釋出iOSBook13","UserID":"tony"},
{"ID":"15","CDate":"2014-12-37","Content":"釋出iOSBook14","UserID":"tony"},
{"ID":"16","CDate":"2014-12-38","Content":"釋出iOSBook15","UserID":"tony"},
{"ID":"17","CDate":"2014-12-39","Content":"釋出iOSBook16","UserID":"tony"},
{"ID":"18","CDate":"2014-12-40","Content":"釋出iOSBook17","UserID":"tony"},
{"ID":"19","CDate":"2014-12-41","Content":"釋出iOSBook18","UserID":"tony"},
{"ID":"20","CDate":"2014-12-42","Content":"釋出iOSBook19","UserID":"tony"},
{"ID":"21","CDate":"2014-12-43","Content":"釋出iOSBook20","UserID":"tony"},
{"ID":"22","CDate":"2014-12-44","Content":"釋出iOSBook21","UserID":"tony"}]}

示例程式碼

import UIKit

class ViewController: UIViewController {

    var objects:NSMutableArray!=[]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let path=NSBundle.mainBundle().pathForResource("Notes", ofType: "json")!
        let jsonData=NSData(contentsOfFile: path)!

        //MutableContainers指定解析返回的是可變的陣列或字典
        let jsonObj:NSDictionary=(try? NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary

        self.objects=jsonObj.objectForKey("Record") as! NSMutableArray

        NSLog("\(self.objects)")
    }

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


}

執行結果

相關文章