一、XML簡單介紹
XML:全稱是Extensible Markup Language,譯作“可擴展標記語言”
跟JSON一樣,也是常用的一種用於交互的數據格式,一般也叫XML文檔(XML Document)
XML舉例
<videos>
<video name="小黃人 第01部" length="30" />
<video name="小黃人 第02部" length="19" />
<video name="小黃人 第03部" length="33" />
</videos>

二、XML的語法
1.簡單說明
一個常見的XML文檔一般由以下部分組成
文檔聲明
元素(Element)
屬性(Attribute)
2.文檔聲明
在XML文檔的最前面,必須編寫一個文檔聲明,用來聲明XML文檔的類型
最簡單的聲明
<?xml version="1.0" ?>
用encoding屬性說明文檔的字符編碼
<?xml version="1.0" encoding="UTF-8" ?>
3.XML語法 – 元素(Element)
一個元素包括了開始標簽和結束標簽
擁有元素內容:<video>小黃人</video>
沒有元素內容:<video></video>
沒有元素內容的簡寫:<video/>
一個元素可以嵌套若干個子元素(不能出現交叉嵌套)
<videos>
<video>
<name>小黃人 第01部</name>
<length>30</length>
</video>
</videos>
注意:
(1)規范的XML文檔最多只有1個根元素,其他元素都是根元素的子孫元素
(2)XML中的所有空格和換行,都會當做具體內容處理
下面兩個元素的內容是不一樣的
第1個
<video>小黃人</video>
第2個
<video>
小黃人
</video>
4.XML語法 – 屬性(Attribute)
一個元素可以擁有多個屬性
<video name="小黃人 第01部" length="30" /> ====》video元素擁有name和length兩個屬性
注意:屬性值必須用 雙引號"" 或者 單引號'' 括住
實際上,屬性表示的信息也可以用子元素來表示,比如
<video>
<name>小黃人 第01部</name>
<length>30</length>
</video>
三、XML的解析
1.簡單說明
要想從XML中提取有用的信息,必須得學會解析XML
提取name元素里面的內容
<name>小黃人 第01部</name>
提取video元素中name和length屬性的值
<video name="小黃人 第01部" length="30" />
XML的解析方式有2種
(1)DOM:一次性將整個XML文檔加載進內存,比較適合解析小文件
(3)SAX:從根元素開始,按順序一個元素一個元素往下解析,比較適合解析大文件
2.IOS開發中XML的解析
在iOS中,解析XML的手段有很多
(1)蘋果原生 NSXMLParser:SAX方式解析,使用簡單
(2)第三方框架
1)libxml2:純C語言,默認包含在iOS SDK中,同時支持DOM和SAX方式解析
2)GDataXML:DOM方式解析,由Google開發,基於libxml2
XML解析方式的選擇建議:
大文件:NSXMLParser、libxml2
小文件:GDataXML
3.NSXMLParser
(1)使用步驟
// 1.傳入XML數據,創建解析器
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
// 2.設置代理,監聽解析過程
parser.delegate = self;
// 3.開始解析
[parser parse];
(2)說明
NSXMLParser采取的是SAX方式解析,特點是事件驅動,下面情況都會通知代理
當掃描到文檔(Document)的開始與結束
當掃描到元素(Element)的開始與結束
(3)NSXMLParserDelegate
1)當掃描到文檔的開始時調用(開始解析)- (void)parserDidStartDocument:(NSXMLParser *)parser
2)當掃描到文檔的結束時調用(解析完畢)- (void)parserDidEndDocument:(NSXMLParser *)parser
3)當掃描到元素的開始時調用(attributeDict存放着元素的屬性)- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
4)當掃描到元素的結束時調用 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
(4)代碼示例
1 //
2 // YYViewController.m
3 // 01-文頂頂客戶端
4 //
5 // Created by apple on 14-6-29.
6 // Copyright (c) 2014年 itcase. All rights reserved.
7 //
8
9 #import "YYViewController.h"
10 #import "MBProgressHUD+MJ.h"
11 #import "YYviodesModel.h"
12 #import "YYCell.h"
13 #import <MediaPlayer/MediaPlayer.h>
14 #import "YYMoviePlayerViewController.h"
15
16 @interface YYViewController ()<NSXMLParserDelegate>
17 @property(nonatomic,strong)NSArray *videos;
18
19 @end
20
21 @implementation YYViewController
22
23 - (void)viewDidLoad
24 {
25 [super viewDidLoad];
26 //去掉下划線
27 self.tableView.separatorStyle=UITableViewCellSeparatorStyleNone;
28
29 [MBProgressHUD showMessage:@"正在努力加載中"];
30
31 //創建路徑
32
33 NSString *urlStr=@"http://192.168.1.53:8080/MJServer/video?type=XML";
34 NSURL *url=[NSURL URLWithString:urlStr];
35
36 //創建請求
37 NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];//默認為get請求
38 //設置最大的網絡等待時間
39 request.timeoutInterval=20.0;
40
41 //獲取主隊列
42 NSOperationQueue *queue=[NSOperationQueue mainQueue];
43 //發起請求
44 [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
45 //隱藏HUD
46 [MBProgressHUD hideHUD];
47 if (data) {//如果請求成功,拿到服務器返回的數據
48 [self parseXMLData:data];
49
50 // //解析拿到的數據(JSON方式)
51 // NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
52 //// NSArray *array=dict[@"video"];
53 // NSArray *array=dict[@"videos"];
54 //
55 // NSMutableArray *videos=[NSMutableArray array];
56 // for (NSDictionary *dict in array) {
57 // YYviodesModel *model=[YYviodesModel viodesModelWithDict:dict];
58 // [videos addObject:model];
59 // }
60 // self.videos=videos;
61
62 //刷新表格
63 [self.tableView reloadData];
64
65 }else//如果請求失敗,沒有拿到數據
66 {
67 [MBProgressHUD showError:@"網絡繁忙,等稍后再試!"];
68 }
69 }];
70 }
71
72 /**
73 * 解析XML數據
74 */
75 -(void)parseXMLData:(NSData *)data
76 {
77 //1.創建解析器
78 NSXMLParser *parser=[[NSXMLParser alloc]initWithData:data];
79 //2.設置代理
80 parser.delegate=self;
81
82 //3.開始解析
83 [parser parse];
84 }
85
86 #pragma mark-NSXMLParserDelegate
87 /**
88 *開始解析文檔時調用
89 */
90 -(void)parserDidStartDocument:(NSXMLParser *)parser
91 {
92 NSLog(@"開始解析文檔");
93 }
94 /**
95 *結束解析文檔時調用(解析完畢)
96 */
97 -(void)parserDidEndDocument:(NSXMLParser *)parser
98 {
99 NSLog(@"結束解析文檔");
100 }
101 /**
102 *解析到一個元素的開頭時調用
103 */
104 -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
105 {
106 NSLog(@"解析到一個元素的開頭---%@",elementName);
107 }
108 /**
109 *解析到一個元素的結尾時調用
110 */
111 -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
112 {
113 NSLog(@"解析到一個元素的結尾---%@",elementName);
114 }
115 #pragma mark-數據源方法
116 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
117 {
118 return 1;
119 }
120 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
121 {
122 return self.videos.count;
123 }
124 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
125 {
126 YYCell *cell=[YYCell cellWithTableView:tableView];
127 //獲取數據模型
128 cell.model=self.videos[indexPath.row];
129 return cell;
130 }
131
132 //設置cell的行高
133 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
134 {
135 return 70;
136 }
137
138 //播放視頻
139 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
140 {
141 //取出數據模型
142 YYviodesModel *model=self.videos[indexPath.row];
143
144 //創建視屏播放器
145 // MPMoviePlayerController 可以隨意控制播放器的尺寸
146 //MPMoviePlayerViewController只能全屏播放
147
148 NSString *url = [NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/%@", model.url];
149 NSURL *videoUrl=[NSURL URLWithString:url];
150 YYMoviePlayerViewController *movieVc=[[YYMoviePlayerViewController alloc]initWithContentURL:videoUrl];
151 //彈出播放器
152 [self presentMoviePlayerViewControllerAnimated:movieVc];
153 // UIApplicationDidEnterBackgroundNotification
154 }
155
156
157 @end
打印查看

(5)完成完整的功能
1 //
2 // YYViewController.m
3 // 01-文頂頂客戶端
4 //
5 // Created by apple on 14-6-29.
6 // Copyright (c) 2014年 itcase. All rights reserved.
7 //
8
9 #import "YYViewController.h"
10 #import "MBProgressHUD+MJ.h"
11 #import "YYviodesModel.h"
12 #import "YYCell.h"
13 #import <MediaPlayer/MediaPlayer.h>
14 #import "YYMoviePlayerViewController.h"
15
16 @interface YYViewController ()<NSXMLParserDelegate>
17 @property(nonatomic,strong)NSMutableArray *videos;
18
19 @end
20
21 @implementation YYViewController
22
23 - (void)viewDidLoad
24 {
25 [super viewDidLoad];
26 //去掉下划線
27 self.tableView.separatorStyle=UITableViewCellSeparatorStyleNone;
28
29 [MBProgressHUD showMessage:@"正在努力加載中"];
30
31 //創建路徑
32
33 NSString *urlStr=@"http://192.168.1.53:8080/MJServer/video?type=XML";
34 NSURL *url=[NSURL URLWithString:urlStr];
35
36 //創建請求
37 NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];//默認為get請求
38 //設置最大的網絡等待時間
39 request.timeoutInterval=20.0;
40
41 //獲取主隊列
42 NSOperationQueue *queue=[NSOperationQueue mainQueue];
43 //發起請求
44 [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
45 //隱藏HUD
46 [MBProgressHUD hideHUD];
47 if (data) {//如果請求成功,拿到服務器返回的數據
48 //解析XML數據
49 [self parseXMLData:data];
50 }else//如果請求失敗,沒有拿到數據
51 {
52 [MBProgressHUD showError:@"網絡繁忙,等稍后再試!"];
53 }
54 }];
55 }
56
57 /**
58 * 解析XML數據
59 */
60 -(void)parseXMLData:(NSData *)data
61 {
62 //1.創建解析器
63 NSXMLParser *parser=[[NSXMLParser alloc]initWithData:data];
64 //2.設置代理
65 parser.delegate=self;
66
67 //3.開始解析
68 [parser parse]; //這個方法會卡住(同步解析,解析完畢后才會返回)
69
70 //4.刷新表格
71 [self.tableView reloadData];
72 }
73
74 #pragma mark-NSXMLParserDelegate
75 /**
76 *開始解析文檔時調用
77 */
78 -(void)parserDidStartDocument:(NSXMLParser *)parser
79 {
80 NSLog(@"開始解析文檔");
81 }
82 /**
83 *結束解析文檔時調用(解析完畢)
84 */
85 -(void)parserDidEndDocument:(NSXMLParser *)parser
86 {
87 NSLog(@"結束解析文檔");
88 //也可以在這里刷新表格
89 // [self.tableView reloadData];
90 }
91 /**
92 *解析到一個元素的開頭時調用
93 */
94 -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
95 {
96 // NSLog(@"解析到一個元素的開頭---%@",elementName);
97 if ([@"videos" isEqualToString:elementName]) {//解析到一個videos標簽
98 self.videos=[NSMutableArray array];
99 }else if ([@"video" isEqualToString:elementName])
100 {//解析到一個video標簽,創建一個模型
101 YYviodesModel *model=[YYviodesModel viodesModelWithDict:attributeDict];
102 [self.videos addObject:model];
103 }
104 }
105 /**
106 *解析到一個元素的結尾時調用
107 */
108 -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
109 {
110 NSLog(@"解析到一個元素的結尾---%@",elementName);
111 }
112 #pragma mark-數據源方法
113 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
114 {
115 return 1;
116 }
117 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
118 {
119 return self.videos.count;
120 }
121 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
122 {
123 YYCell *cell=[YYCell cellWithTableView:tableView];
124 //獲取數據模型
125 cell.model=self.videos[indexPath.row];
126 return cell;
127 }
128
129 //設置cell的行高
130 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
131 {
132 return 70;
133 }
134
135 //播放視頻
136 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
137 {
138 //取出數據模型
139 YYviodesModel *model=self.videos[indexPath.row];
140
141 //創建視屏播放器
142 // MPMoviePlayerController 可以隨意控制播放器的尺寸
143 //MPMoviePlayerViewController只能全屏播放
144
145 NSString *url = [NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/%@", model.url];
146 NSURL *videoUrl=[NSURL URLWithString:url];
147 YYMoviePlayerViewController *movieVc=[[YYMoviePlayerViewController alloc]initWithContentURL:videoUrl];
148 //彈出播放器
149 [self presentMoviePlayerViewControllerAnimated:movieVc];
150 // UIApplicationDidEnterBackgroundNotification
151 }
152
153
154 @end
注意:注意刷新代碼的操作,在進行解析的時候,需要對標簽進行判斷。
四、基於NSXMLParser(SAX)封裝解析數據的代碼(包括JSON和XML的解析)
封裝后的主控制器代碼:
1 //
2 // YYViewController.m
3 // 01-文頂頂客戶端
4 //
5 // Created by apple on 14-6-29.
6 // Copyright (c) 2014年 itcase. All rights reserved.
7 //
8
9 #import "YYViewController.h"
10 #import "MBProgressHUD+MJ.h"
11 #import "YYviodesModel.h"
12 #import "YYCell.h"
13 #import <MediaPlayer/MediaPlayer.h>
14 #import "YYMoviePlayerViewController.h"
15 #import "YYtool.h"
16
17 @interface YYViewController ()
18 @property(nonatomic,strong)NSArray *videos;
19 @end
20
21 @implementation YYViewController
22
23 -(NSArray *)videos
24 {
25 if (_videos==nil) {
26 _videos=[NSArray array];
27 }
28 return _videos;
29 }
30 - (void)viewDidLoad
31 {
32 [super viewDidLoad];
33 //去掉下划線
34 self.tableView.separatorStyle=UITableViewCellSeparatorStyleNone;
35
36 [MBProgressHUD showMessage:@"正在努力加載中"];
37
38 //創建路徑
39
40 NSString *urlStr=@"http://192.168.1.53:8080/MJServer/video?type=JSON";
41 NSURL *url=[NSURL URLWithString:urlStr];
42
43 //創建請求
44 NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];//默認為get請求
45 //設置最大的網絡等待時間
46 request.timeoutInterval=20.0;
47
48 //獲取主隊列
49 NSOperationQueue *queue=[NSOperationQueue mainQueue];
50 //發起請求
51 [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
52 //隱藏HUD
53 [MBProgressHUD hideHUD];
54 if (data) {//如果請求成功,拿到服務器返回的數據
55 //解析XML數據
56 YYtool *tool=[[YYtool alloc]init];
57 // [tool parseXMLData:data];
58 self.videos=[tool parseJSONData:data];
59 //刷新表格
60 [self.tableView reloadData];
61 }else//如果請求失敗,沒有拿到數據
62 {
63 [MBProgressHUD showError:@"網絡繁忙,等稍后再試!"];
64 }
65 }];
66 }
67
68
69 #pragma mark-數據源方法
70 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
71 {
72 return 1;
73 }
74 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
75 {
76 return self.videos.count;
77 }
78 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
79 {
80 YYCell *cell=[YYCell cellWithTableView:tableView];
81 //獲取數據模型
82 cell.model=self.videos[indexPath.row];
83 return cell;
84 }
85
86 //設置cell的行高
87 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
88 {
89 return 70;
90 }
91
92 //播放視頻
93 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
94 {
95 //取出數據模型
96 YYviodesModel *model=self.videos[indexPath.row];
97
98 //創建視屏播放器
99 // MPMoviePlayerController 可以隨意控制播放器的尺寸
100 //MPMoviePlayerViewController只能全屏播放
101
102 NSString *url = [NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/%@", model.url];
103 NSURL *videoUrl=[NSURL URLWithString:url];
104 YYMoviePlayerViewController *movieVc=[[YYMoviePlayerViewController alloc]initWithContentURL:videoUrl];
105 //彈出播放器
106 [self presentMoviePlayerViewControllerAnimated:movieVc];
107 // UIApplicationDidEnterBackgroundNotification
108 }
109 @end
封裝的解析類的頭文件
1 //
2 // YYtool.h
3 // 01-文頂頂客戶端
4 //
5 // Created by apple on 14-6-29.
6 // Copyright (c) 2014年 itcase. All rights reserved.
7 //
8
9 #import <Foundation/Foundation.h>
10
11 @interface YYtool : NSObject
12 -(NSArray *)parseXMLData:(NSData *)data;
13 -(NSArray *)parseJSONData:(NSData *)data;
14
15 @end
封裝的解析類的內部實現:
1 //
2 // YYtool.m
3 // 01-文頂頂客戶端
4 //
5 // Created by apple on 14-6-29.
6 // Copyright (c) 2014年 itcase. All rights reserved.
7 //
8
9 #import "YYtool.h"
10 #import "YYviodesModel.h"
11
12 @interface YYtool ()<NSXMLParserDelegate>
13 @property(nonatomic,strong)NSMutableArray *videos;
14 @end
15 @implementation YYtool
16
17 -(NSArray *)parseJSONData:(NSData *)data
18 {
19 NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
20 // NSArray *array=dict[@"video"];
21 NSArray *array=dict[@"videos"];
22
23 NSMutableArray *videos=[NSMutableArray array];
24 for (NSDictionary *dict in array) {
25 YYviodesModel *model=[YYviodesModel viodesModelWithDict:dict];
26 [videos addObject:model];
27 }
28 return videos;
29 }
30
31 -(NSArray *)parseXMLData:(NSData *)data
32 {
33 //1.創建解析器
34 NSXMLParser *parser=[[NSXMLParser alloc]initWithData:data];
35 //2.設置代理
36 parser.delegate=self;
37
38 //3.開始解析
39 [parser parse]; //這個方法會卡住(同步解析,解析完畢后才會返回)
40
41 return self.videos;
42 }
43
44 #pragma mark-NSXMLParserDelegate
45 /**
46 *開始解析文檔時調用
47 */
48 -(void)parserDidStartDocument:(NSXMLParser *)parser
49 {
50 NSLog(@"開始解析文檔");
51 }
52 /**
53 *結束解析文檔時調用(解析完畢)
54 */
55 -(void)parserDidEndDocument:(NSXMLParser *)parser
56 {
57 NSLog(@"結束解析文檔");
58 //也可以在這里刷新表格
59 // [self.tableView reloadData];
60 }
61 /**
62 *解析到一個元素的開頭時調用
63 */
64 -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
65 {
66 if ([@"videos" isEqualToString:elementName]) {//解析到一個videos標簽
67 self.videos=[NSMutableArray array];
68 }else if ([@"video" isEqualToString:elementName])
69 {//解析到一個video標簽,創建一個模型
70 YYviodesModel *model=[YYviodesModel viodesModelWithDict:attributeDict];
71 [self.videos addObject:model];
72 }
73 }
74 /**
75 *解析到一個元素的結尾時調用
76 */
77 -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
78 {
79 NSLog(@"解析到一個元素的結尾---%@",elementName);
80 }
81
82 @end
五、GDataXML
1.配置
GDataXML基於libxml2庫,得做以下配置
導入libxml2庫

該動態庫內部沒有頭文件,所以還需要設置libxml2的頭文件搜索路徑(為了能找到libxml2庫的所有頭文件)
在Head Search Path中加入/usr/include/libxml2

該庫是2008年的,未使用ARC進行內存管理,所以還需要告訴編譯器,對它進行非ARC處理。

設置鏈接參數(自動鏈接libxml2庫)
在Other Linker Flags中加入-lxml2

2.GDataXML使用
GDataXML中常用的類
GDataXMLDocument:代表整個XML文檔
GDataXMLElement
代表文檔中的每個元素
使用attributeForName:方法可以獲得屬性值
代碼示例:
1 //
2 // YYViewController.m
3 // 01-文頂頂客戶端
4 //
5 // Created by apple on 14-6-29.
6 // Copyright (c) 2014年 itcase. All rights reserved.
7 //
8
9 #import "YYViewController.h"
10 #import "MBProgressHUD+MJ.h"
11 #import "YYviodesModel.h"
12 #import "YYCell.h"
13 #import <MediaPlayer/MediaPlayer.h>
14 #import "YYMoviePlayerViewController.h"
15 #import "GDataXMLNode.h"
16
17 @interface YYViewController ()<NSXMLParserDelegate>
18 @property(nonatomic,strong)NSMutableArray *videos;
19
20 @end
21
22 @implementation YYViewController
23
24 - (void)viewDidLoad
25 {
26 [super viewDidLoad];
27 //去掉下划線
28 self.tableView.separatorStyle=UITableViewCellSeparatorStyleNone;
29
30 [MBProgressHUD showMessage:@"正在努力加載中"];
31
32 //創建路徑
33
34 NSString *urlStr=@"http://192.168.1.53:8080/MJServer/video?type=XML";
35 NSURL *url=[NSURL URLWithString:urlStr];
36
37 //創建請求
38 NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];//默認為get請求
39 //設置最大的網絡等待時間
40 request.timeoutInterval=20.0;
41
42 //獲取主隊列
43 NSOperationQueue *queue=[NSOperationQueue mainQueue];
44 //發起請求
45 [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
46 //隱藏HUD
47 [MBProgressHUD hideHUD];
48 if (data) {//如果請求成功,拿到服務器返回的數據
49 //解析XML數據
50 [self parseXMLData:data];
51 }else//如果請求失敗,沒有拿到數據
52 {
53 [MBProgressHUD showError:@"網絡繁忙,等稍后再試!"];
54 }
55 }];
56 }
57
58 /**
59 * DOM方式解析XML數據
60 */
61 -(void)parseXMLData:(NSData *)data
62 {
63 //1.加載文檔
64 GDataXMLDocument *doc=[[GDataXMLDocument alloc]initWithData:data options:0 error:nil];
65 //2.獲得根元素
66 GDataXMLElement *root=doc.rootElement;
67 //3.獲得所有的video元素
68 NSArray *elements=[root elementsForName:@"video"];
69 //4.將GDataXMLElement對象轉換成模型
70 NSMutableArray *videos=[NSMutableArray array];
71 for (GDataXMLElement *ele in elements) {
72 YYviodesModel *model=[[YYviodesModel alloc]init];
73 model.ID=[ele attributeForName:@"id"].stringValue.intValue;
74 model.length=[ele attributeForName:@"length"].stringValue.intValue;
75 model.name=[ele attributeForName:@"name"].stringValue;
76 model.image=[ele attributeForName:@"image"].stringValue;
77 model.url=[ele attributeForName:@"url"].stringValue;
78 [videos addObject:model];
79 }
80 self.videos=videos;
81 //4.刷新表格
82 [self.tableView reloadData];
83 }
84
85 #pragma mark-數據源方法
86 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
87 {
88 return 1;
89 }
90 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
91 {
92 return self.videos.count;
93 }
94 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
95 {
96 YYCell *cell=[YYCell cellWithTableView:tableView];
97 //獲取數據模型
98 cell.model=self.videos[indexPath.row];
99 return cell;
100 }
101
102 //設置cell的行高
103 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
104 {
105 return 70;
106 }
107
108 //播放視頻
109 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
110 {
111 //取出數據模型
112 YYviodesModel *model=self.videos[indexPath.row];
113
114 //創建視屏播放器
115 // MPMoviePlayerController 可以隨意控制播放器的尺寸
116 //MPMoviePlayerViewController只能全屏播放
117
118 NSString *url = [NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/%@", model.url];
119 NSURL *videoUrl=[NSURL URLWithString:url];
120 YYMoviePlayerViewController *movieVc=[[YYMoviePlayerViewController alloc]initWithContentURL:videoUrl];
121 //彈出播放器
122 [self presentMoviePlayerViewControllerAnimated:movieVc];
123 // UIApplicationDidEnterBackgroundNotification
124 }
125 @end
執行:

IOS學習之十六:網絡數據的XML解析
網絡應用中的數據解析,因為最近的應用,無論是Android的和ios平台的,一直用也是建議用的都是Json解析,
xml解析都有點被遺忘了。
然后最近自己在做着玩一個ios的小應用,涉及網絡數據的抓取,一些網站可能都提供了自己api平台,這些一般都是支持
我們對於數據協議格式的設定的。但是后來我在找尋到一些Rss資源時,發現返回的數據都是xml格式的,
因此,那就只好用xml解析了。
XML解析其實這個概念出現了算夠久了,以前javaweb什么到處都在用。這邊我們主要大致介紹下,然后在在ios編程如何使用。
XML解析一般分兩種模式SAX和DOM,事件和文檔。具體解析google去吧,有詳細。不過看了下面的兩個例子,一般就了解了。
一:XML解析之SAX解析,以及對NSXMLParser的應用。
sax解析說白了,就是一個事物模型解析,從頭開始讀取文檔然后根據讀取到的頭標簽標簽時要怎么處理,讀完頭標簽后,理論上是讀取標簽值了,
然后讀取后遇到結束標簽等
簡單舉個例子
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"> 頭標簽,里面的xmlns,可以看成是屬性
<channel>
<title>呵呵呵呵</title>結束標簽,中間的“呵呵呵呵”是首尾標簽標簽值空間
.......
好了,那么在ios開發中如何使用。
SDK本身是提供了NSXMLParser解析器。
- -(BOOL)parser:(NSString*)string
- {
- //系統自帶的
- NSXMLParser *par = [[[NSXMLParser alloc] initWithData:[string dataUsingEncoding:NSUTF8StringEncoding]]autorelease];
- [par setDelegate:self];//設置NSXMLParser對象的解析方法代理
- return [par parse];//調用代理解析NSXMLParser對象,看解析是否成功 }
- }
- #pragma mark xmlparser
- //step 1 :准備解析
- - (void)parserDidStartDocument:(NSXMLParser *)parser
- {
- // NSLog(@"%@",NSStringFromSelector(_cmd) );
- }
- //step 2:准備解析節點
- - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
- {
- // NSLog(@"%@",NSStringFromSelector(_cmd) );
- }
- //step 3:獲取首尾節點間內容
- - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
- {
- NSLog(@"%@",NSStringFromSelector(_cmd) );
- }
- //step 4 :解析完當前節點
- - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
- {
- NSLog(@"%@",NSStringFromSelector(_cmd) );
- }
- //step 5;解析結束
- - (void)parserDidEndDocument:(NSXMLParser *)parser
- {
- // NSLog(@"%@",NSStringFromSelector(_cmd) );
- }
- //獲取cdata塊數據
- - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock
- {
- // NSLog(@"%@",NSStringFromSelector(_cmd) );
- }
1.初始化解析器,傳入你要解析的數據。
2.parse,啟動解析,返回一個是否解析成功Bool值。
3.基本你要處理的就在下面實現的1-5個代理方法了。
其實代理方法和詳細,就是一個事物進行流程:
step1是准備解析,然后沒意外就是執行到了——>
step2讀取到第一個頭節點了,然后如果內部有屬性值,你可以獲取出來,讀完頭節點,我們會進去值域——》
step3對於簡單的節點,可能直接就是一個string值了,但是看例子我們會知道,很多情況下,該節點的值域包含的於是一個節點——》
這步其實分兩種,如果是值,那么就是執行step4,獲取值的字竄,如果是子節點呢,我們一看就知道,它又是進行了step2,
即讀取到頭標簽了,其實你是很人讀一片文章流程一樣,只不過我們腦中有個印象<xxx>是頭標簽了,我們要做什么,獨到 頭標簽的最后一個符號">"
下面進去值域,獨到了字竄的話就調用了foundCharacters:(NSString *)string,如果又讀到<xxx>這樣的,那就又是頭標簽了。——》
step5就是讀到開始尾標簽符號了。
最后一個方法
foundCDATA:(NSData *)CDATABlock,其實也是一個格式
- <content:encoded>
- <![CDATA[
- <img src="http://img1.douban.com/mpic/s10489201.jpg" style="float:right;margin-left:16px"/><a href="http://www.douban.com/people/maldini/">減卐肥™</a>評論: <a href="http://movie.douban.com/subject/6799191//">搜索</a><br/> <br/>評價: 力薦<br/><br/>
- ]]>
- </content:encoded>
好了,方法和流程大致了解了,拿一個我最近遇到的例子,好多時候,我們會遇到這樣讀取一組類似於json中數組形式的數據
- <channel>
- <title>我是標題</title>
- <link>http://write.blog.csdn.net/postedit</link>
- <description>...</description>
- <language>zh-cn</language>
- <pubDate>Fri, 03 Aug 2012 06:20:31 GMT</pubDate>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- <item>...</item>
- </channel>
一般來說,我們要的數據其實都是這20個item,對吧,每個item下都是相同的3個標簽,title,author,time。形式上
- #pragma mark xmlparser
- //step 1 :准備解析
- - (void)parserDidStartDocument:(NSXMLParser *)parser
- {
- // NSLog(@"%@",NSStringFromSelector(_cmd) );
- parserObjects = [[NSMutableArray alloc]init];
- }
- //step 2:准備解析節點
- - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
- {
- // NSLog(@"%@",NSStringFromSelector(_cmd) );
- self.currentText = [[NSMutableString alloc]init];
- [currentText release];
- if ([elementName isEqualToString:@"item"]) {
- NSMutableDictionary *newNode = [[ NSMutableDictionary alloc ] initWithCapacity : 0 ];
- twitterDic = newNode;
- [parserObjects addObject :newNode];
- [newNode release];
- }
- else if(twitterDic) {
- NSMutableString *string = [[ NSMutableString alloc ] initWithCapacity : 0 ];
- [twitterDic setObject :string forKey :elementName];
- [string release ];
- currentElementName = elementName;
- }
- }
- //step 3:獲取首尾節點間內容
- - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
- {
- NSLog(@"%@",NSStringFromSelector(_cmd) );
- [currentText appendString:string];
- }
- //step 4 :解析完當前節點
- - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
- {
- if ([elementName isEqualToString:@"item"]) {
- twitterDic = nil;
- }else
- if ([elementName isEqualToString:currentElementName]) {
- if ([elementName isEqualToString:@"description"]
- ||[elementName isEqualToString:@"content:encoded"]) {
- [twitterDic setObject:Cdata forKey:currentElementName];
- }else {
- [twitterDic setObject:currentText forKey:currentElementName];
- }
- }
- }
- //step 5;解析結束
- - (void)parserDidEndDocument:(NSXMLParser *)parser
- {
- }
- //獲取cdata塊數據
- - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock
- {
- Cdata =[[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding];
- }
對於上面代碼說幾點
注意這個代理方法的注釋
// This returns the string of the characters encountered thus far. You may not necessarily get the longest character run. The parser reserves the right to hand these to the delegate as potentially many calls in a row to -parser:foundCharacters:
下面是google翻譯。
這將返回迄今為止遇到的字符的字符串。你不一定得到的最長字符運行。解析器有權交行解析器可能多次呼吁這些委托:foundCharacters:
這個說明,在獲取一個標簽首尾間的字符數據時,這個方法可能被調用多次。
舉個我碰到的最簡單的列子
<copyright>© 2012, douban.com.</copyright>
我在解析這個節點時,上面方法就調用了兩次,
第一次只返回&,緊接着第二次返回copy; 2012, douban.com.
因此你如果要獲取完整的的,應該用string的append方法來獲取完整的一條記錄。
- //- (void)recurrence:(TBXMLElement *)element {
- //
- // NSString *eleName = [TBXML elementName:element];
- // NSString *eleText = [TBXML textForElement:element];
- // if ([eleName isEqualToString:@"item"]) {
- // self recurrence:element
- // }
- //
- //
- //
- //
- // do {
- //
- // NSString *eleName = [TBXML elementName:element];
- // NSString *eleText = [TBXML textForElement:element];
- //
- // //遞歸處理子樹
- // if (element->firstChild) {
- // NSLog(@"<%@>:",eleName);// Display the name of the element
- //
- // [self recurrence:element->firstChild];
- // }else {
- // NSLog(@"<%@>:%@",eleName,eleText);// Display the name of the element
- //
- // TBXMLElement *parent = element->parentElement;
- // if ([[TBXML elementName:parent] isEqualToString:@"item"]) {
- // NLRssInfo *info = [[[NLRssInfo alloc]init] autorelease];
- //
- // if ([eleName isEqualToString:@"title"]) {
- // info.title = eleText;
- // }
- //
- //
- // [dataArr addObject:info];
- // }
- //
- // }
- //
- //
- // //迭代處理兄弟樹
- // } while ((element = element->nextSibling));
- //}


