Swift - 解析XML格式数据(分别使用GDataXML和DDXML)

XML解析方式的选择建议
  • 大文件用:NSXMLParser
  • 小文件用:GDataXML

假设需要被解析的XML数据文件video.xml如下:

<videos>
<video id="1" name="小黄人 第01部" length="10" image="resources/images/minion_01.png" url="resources/videos/minion_01.mp4"/>
<video id="2" name="小黄人 第02部" length="12" image="resources/images/minion_02.png" url="resources/videos/minion_02.mp4"/>
<video id="3" name="小黄人 第03部" length="14" image="resources/images/minion_03.png" url="resources/videos/minion_03.mp4"/>
<video id="4" name="小黄人 第04部" length="16" image="resources/images/minion_04.png" url="resources/videos/minion_04.mp4"/>
<video id="5" name="小黄人 第05部" length="18" image="resources/images/minion_05.png" url="resources/videos/minion_05.mp4"/>
<video id="6" name="小黄人 第06部" length="20" image="resources/images/minion_06.png" url="resources/videos/minion_06.mp4"/>
<video id="7" name="小黄人 第07部" length="22" image="resources/images/minion_07.png" url="resources/videos/minion_07.mp4"/>
<video id="8" name="小黄人 第08部" length="24" image="resources/images/minion_08.png" url="resources/videos/minion_08.mp4"/>
<video id="9" name="小黄人 第09部" length="26" image="resources/images/minion_09.png" url="resources/videos/minion_09.mp4"/>
<video id="10" name="小黄人 第10部" length="28" image="resources/images/minion_10.png" url="resources/videos/minion_10.mp4"/>
<video id="11" name="小黄人 第11部" length="30" image="resources/images/minion_11.png" url="resources/videos/minion_11.mp4"/>
<video id="12" name="小黄人 第12部" length="32" image="resources/images/minion_12.png" url="resources/videos/minion_12.mp4"/>
<video id="13" name="小黄人 第13部" length="34" image="resources/images/minion_13.png" url="resources/videos/minion_13.mp4"/>
<video id="14" name="小黄人 第14部" length="36" image="resources/images/minion_14.png" url="resources/videos/minion_14.mp4"/>
<video id="15" name="小黄人 第15部" length="38" image="resources/images/minion_15.png" url="resources/videos/minion_15.mp4"/>
<video id="16" name="小黄人 第16部" length="40" image="resources/images/minion_16.png" url="resources/videos/minion_16.mp4"/>
</videos>

一,使用GDataXML(这个是google出品的)

  1. 在Build Phases -> Link Binary With Libraries中,点击“+”添加“libxml2.2.tbd”
  2. 在Build Setting -> Header Search Paths里添加
    ${SDK_DIR}/usr/include/libxml2


  1. 在Build Setting -> Other Linker Flags 里添加 -lxml2


  1. 在Build Phases里找到GDataXMLNode.m文件设置为非ARC(-fno-objc-arc)


  1. 添加bridge.h头文件并设置到编译参数里
#import "GDataXMLNode.h"
  1. 导入GDataXML库文件(GDataXMLNode.h和GDataXMLNode.m),代码结构如下:
  1. 开始解析(ViewController.swift)
import UIKit
import MediaPlayer

class VideosTableViewController: UITableViewController {
    lazy var videos: NSMutableArray = {
        return NSMutableArray()
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        /*
        加载服务器最新的视频信息
        */
        let urlStr = String(format: "http://localhost:8080/MJServer/video")
        let url = NSURL(string: urlStr)
        // 创建一个请求
        let request = NSMutableURLRequest(URL: url!)
        request.HTTPMethod = "POST"
        // 设置请求体(参数)
        let param = String(format: "type=%@", "XML")
        // 设置字符串编码
        request.HTTPBody = param.dataUsingEncoding(NSUTF8StringEncoding)

        // 发送异步请求
        let queue = NSOperationQueue.mainQueue()
        NSURLConnection.sendAsynchronousRequest(request, queue: queue) { (request, data, error) -> Void in
            if error != nil || data == nil {
                MBProgressHUD.showError("网络繁忙")
                return
            }
            
            // 加载整个XML数据
            let doc = try! GDataXMLDocument(data: data!, options: 0)
            // 获取文档的根节点
            let root = doc.rootElement()
            // 获得根节点里面所有的video元素
            let elements = root.elementsForName("video") as! [GDataXMLElement]
            // 遍历所有的video元素
            for videoElement in elements {
                let video: Video = Video()
                // 取出元素的属性
                video.id = videoElement.attributeForName("id").stringValue()
                video.name = videoElement.attributeForName("name").stringValue()
                video.image = videoElement.attributeForName("image").stringValue()
                video.url = videoElement.attributeForName("url").stringValue()
                video.length = videoElement.attributeForName("length").stringValue()
                
                // 添加到数组中
                self.videos.addObject(video)
            }
            
            self.tableView.reloadData()
        }
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.videos.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let id = "video"
        var cell = tableView.dequeueReusableCellWithIdentifier(id)
        if cell == nil {
            cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: id)
        }
        let video = self.videos[indexPath.row] as! Video
        
        cell?.textLabel?.text = video.name
        cell?.detailTextLabel?.text = String(format: "时长: %d 分钟", video.length!)
        
       
        let urlStr = String(format: "http://localhost:8080/MJServer/%@", video.image!)
        let url = NSURL(string: urlStr)
        // 这里使用了SDWebImage
        cell?.imageView?.sd_setImageWithURL(url, placeholderImage: UIImage(named: "placehoder"))
        
        return cell!
    }

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        // 取出对应的模型
        let video = self.videos[indexPath.row] as! Video
        
        // 创建系统提供的视频播放控制器
        let videoUrl = String(format: "http://localhost:8080/MJServer/%@", video.url!)
        let url = NSURL(string: videoUrl)
        let playerVC = MPMoviePlayerViewController(contentURL: url)
        
        // 显示播放器
        self.presentViewController(playerVC, animated: true, completion: nil)
        
    }
}

二,使用NSXMLParser

import UIKit
import MediaPlayer

class VideosTableViewController: UITableViewController, NSXMLParserDelegate {
    lazy var videos: NSMutableArray = {
        return NSMutableArray()
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        /*
        加载服务器最新的视频信息
        */
        let urlStr = String(format: "http://localhost:8080/MJServer/video")
        let url = NSURL(string: urlStr)
        // 创建一个请求
        let request = NSMutableURLRequest(URL: url!)
        request.HTTPMethod = "POST"
        // 设置请求体(参数)
        let param = String(format: "type=%@", "XML")
        // 设置字符串编码
        request.HTTPBody = param.dataUsingEncoding(NSUTF8StringEncoding)

        // 发送异步请求
        let queue = NSOperationQueue.mainQueue()
        NSURLConnection.sendAsynchronousRequest(request, queue: queue) { (request, data, error) -> Void in
            if error != nil || data == nil {
                MBProgressHUD.showError("网络繁忙")
                return
            }
            
            // 1.创建XML解析器 -- SAX -- 逐个元素往下解析
            let parser = NSXMLParser(data: data!)
            // 2.设置代理
            parser.delegate = self
            // 3.开始解析(同步执行)
            parser.parse()
            
            self.tableView.reloadData()
        }
    }
    /*****************************实现代理方法start***************************/
    /**
     解析到文档的开头时调用
     */
    func parserDidStartDocument(parser: NSXMLParser) {
        
    }
    /**
     解析到一个元素的开始就会调用
     
     - parameter elementName:   元素名称
     - parameter attributeDict: 属性字典
     */
    func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
        if elementName == "videos" {
            // 如果解析的是跟节点直接返回
            return
        }
        // 解析到元素的时候,创建模型赋值
        let video = Video(dict: attributeDict)
        self.videos.addObject(video)
        
    }
    /**
     解析到一个元素的结束就会调用
     
     - parameter elementName:   元素名称
     */
    func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        
    }
    
    /**
     解析到文档的结尾时调用(解析结束)
     */
    func parserDidEndDocument(parser: NSXMLParser) {
        
    }
    /*****************************实现代理方法end***************************/

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.videos.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let id = "video"
        var cell = tableView.dequeueReusableCellWithIdentifier(id)
        if cell == nil {
            cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: id)
        }
        let video = self.videos[indexPath.row] as! Video
        
        cell?.textLabel?.text = video.name
        cell?.detailTextLabel?.text = String(format: "时长: %d 分钟", video.length!)
        
        let urlStr = String(format: "http://localhost:8080/MJServer/%@", video.image!)
        let url = NSURL(string: urlStr)
        cell?.imageView?.sd_setImageWithURL(url, placeholderImage: UIImage(named: "placehoder"))
        
        return cell!
    }

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        // 取出对应的模型
        let video = self.videos[indexPath.row] as! Video
        
        // 创建系统提供的视频播放控制器
        let videoUrl = String(format: "http://localhost:8080/MJServer/%@", video.url!)
        let url = NSURL(string: videoUrl)
        let playerVC = MPMoviePlayerViewController(contentURL: url)
        
        // 显示播放器
        self.presentViewController(playerVC, animated: true, completion: nil)
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容