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出品的)
- 在Build Phases -> Link Binary With Libraries中,点击“+”添加“libxml2.2.tbd”
在Build Setting -> Header Search Paths里添加
${SDK_DIR}/usr/include/libxml2
-
在Build Setting -> Other Linker Flags 里添加 -lxml2
在Build Phases里找到GDataXMLNode.m文件设置为非ARC(-fno-objc-arc)
- 添加bridge.h头文件并设置到编译参数里
#import "GDataXMLNode.h"
- 导入GDataXML库文件(GDataXMLNode.h和GDataXMLNode.m),代码结构如下:
- 开始解析(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)
}
}