iOS网络开发教程之XML解析
程序员文章站
2022-06-16 12:27:48
XML简介
什么是XML?
全称是 ExtensibleMarkupLanguage. 可扩展标记语言.
跟JSON一样,也是常用的一种用于交互的数据格式
一般也叫做XML...
XML简介
什么是XML?
全称是 ExtensibleMarkupLanguage. 可扩展标记语言.
跟JSON一样,也是常用的一种用于交互的数据格式
一般也叫做XML文档 ( XML Document )
XML举例XML语法:
一个常见的XML文档一般由以下部分组成
文档声明
元素 ( Element )
一个元素包括了开始标签和结束标签 拥有内容的元素: <video> 小黄人</video> 没有内容的元素: <video> </video> 没有内容的元素简写: <video> 一个元素可以嵌套若干个子元素(不能出现交叉嵌套) <videos> <video> <name>小黄人 第01部</name> <length>30</length></video> </videos> 规范的XML文档最多只有1个根元素,其他元素都是根元素的子孙元素</video>
属性 ( Attribute )
<video length="30" name="小黄人 第01部"> video元素拥有name和length两个属性 属性值必须用 双引号"" 或者 单引号'' 括住 实际上,属性表示的信息也可以用子元素来表示,比如 <video> <name>小黄人 第01部</name> <length>30</length></video> </video>XML解析
XML的解析方式有2种
DOM: 一次性将整个XML文档加载进内存,比较适合解析小文件SAX: 从根元素开始,按顺序一个元素一个元素往下解析,比较适合 解析大文件SAX解析:( NSXMLParser )
#import "ViewController.h" #import "UIImageView+WebCache.h" #import #import "ZYVideo.h" #import "MJExtension.h" #define baseUrlStr @"https://120.25.226.186:32812" @interface ViewController () /* 存储模型的 数组 */ @property (nonatomic, strong) NSMutableArray *videos; @end @implementation ViewController - (NSMutableArray *)videos { if (!_videos) { _videos = [NSMutableArray array]; } return _videos; } - (void)viewDidLoad { [super viewDidLoad]; // 替换 模型中属性的名称 和 系统关键字冲突.(系统自带方法冲突) [ZYVideo mj_setupReplacedKeyFromPropertyName:^NSDictionary *{ return @{ @"ID" : @"id" }; }]; //1. 确定url NSURL *url = [NSURL URLWithString:@"https://localhost:8080/MJServer/video?method=get&type=XML"]; //2. 创建请求 NSURLRequest *request = [NSURLRequest requestWithURL:url]; //3. 创建异步连接 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) { // 容错处理 if (connectionError) { return ; } // 4. 解析数据(反序列化) NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; parser.delegate = self; // 开始解析: parse方法是 阻塞的, 只有把解析完,才会 调用reloadData [parser parse]; //5. 刷新UI [self.tableView reloadData]; }]; } #pragma -mark NSXMLParser代理方法 // 开始解析 - (void)parserDidStartDocument:(NSXMLParser *)parser { NSLog(@"开始解析----"); } // 开始解析某个元素 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { // NSLog(@"%@---%@",elementName,attributeDict); // SAX解析, 一个一个节点 解析 if ([elementName isEqualToString:@"videos"]) { return; } // 字典转模型 [self.videos addObject:[ZYVideo mj_objectWithKeyValues:attributeDict]]; } // 某个元素解析完毕 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { NSLog(@"%@",elementName); } // 结束解析 - (void)parserDidEndDocument:(NSXMLParser *)parser { NSLog(@"结束解析----"); } #pragma -mark tableView数据源方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.videos.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //1. 设置重用标识 static NSString *ID = @"video"; //2. 在缓存池中复用cell(如果没有会自动创建) UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; //3. 设置数据 // NSDictionary *dict = self.videos[indexPath.row]; ZYVideo *video = self.videos[indexPath.row]; cell.textLabel.text = video.name; cell.detailTextLabel.text = [NSString stringWithFormat:@"播放时间:%@",video.length]; // 使用SDWebImage设置网络中下载的图片 // 拼接图片的url // NSString *baseUrlStr = @"https://120.25.226.186:32812"; NSString *urlStr = [baseUrlStr stringByAppendingPathComponent:video.image]; [cell.imageView sd_setImageWithURL:[NSURL URLWithString:urlStr] placeholderImage:[UIImage imageNamed:@"qq"]]; // NSLog(@"----%@",video.ID); return cell; } #pragma -mark tableView的代理方法 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { //1. 拿到数据 // NSDictionary *dict = self.videos[indexPath.row]; ZYVideo *video = self.videos[indexPath.row]; //2. 拼接资源路径 NSString *urlStr = [baseUrlStr stringByAppendingPathComponent:video.url]; //3. 创建播放器 MPMoviePlayerViewController *mpc = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:urlStr]]; //4. 弹出控制器 [self presentViewController:mpc animated:YES completion:nil]; } @end
DOM解析:(GDataXMLDocument)
使用DOM解析前的配置工作:
1. 导入 GDataXML文件.
#import "ViewController.h" #import "UIImageView+WebCache.h" #import #import "ZYVideo.h" #import "MJExtension.h" #import "GDataXMLNode.h" #define baseUrlStr @"https://120.25.226.186:32812" @interface ViewController () /* 存储模型的 数组 */ @property (nonatomic, strong) NSMutableArray *videos; @end @implementation ViewController - (NSMutableArray *)videos { if (!_videos) { _videos = [NSMutableArray array]; } return _videos; } - (void)viewDidLoad { [super viewDidLoad]; // 替换 模型中属性的名称 和 系统关键字冲突.(系统自带方法冲突) [ZYVideo mj_setupReplacedKeyFromPropertyName:^NSDictionary *{ return @{ @"ID" : @"id" }; }]; //1. 确定url NSURL *url = [NSURL URLWithString:@"https://localhost:8080/MJServer/video?method=get&type=XML"]; //2. 创建请求 NSURLRequest *request = [NSURLRequest requestWithURL:url]; //3. 创建异步连接 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) { // 容错处理 if (connectionError) { return ; } // 4. 解析数据(反序列化) // 4.1 加载整个XML文档 GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil]; //4.2 XML文档的根元素. 拿到根元素内部的 所有名称为video的子孙元素 NSArray *eles = [doc.rootElement elementsForName:@"video"]; //4.3 遍历操作 for (GDataXMLElement *ele in eles) { // 拿到子元素中的属性 ---> 模型 ---> 添加到self.videos ZYVideo *video = [[ZYVideo alloc] init]; video.name = [ele attributeForName:@"name"].stringValue; video.length = [ele attributeForName:@"length"].stringValue; video.image = [ele attributeForName:@"image"].stringValue; video.ID = [ele attributeForName:@"id"].stringValue; video.url = [ele attributeForName:@"url"].stringValue; [self.videos addObject:video]; } //5. 刷新UI [self.tableView reloadData]; }]; } #pragma -mark tableView数据源方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.videos.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //1. 设置重用标识 static NSString *ID = @"video"; //2. 在缓存池中复用cell(如果没有会自动创建) UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; //3. 设置数据 // NSDictionary *dict = self.videos[indexPath.row]; ZYVideo *video = self.videos[indexPath.row]; cell.textLabel.text = video.name; cell.detailTextLabel.text = [NSString stringWithFormat:@"播放时间:%@",video.length]; // 使用SDWebImage设置网络中下载的图片 // 拼接图片的url // NSString *baseUrlStr = @"https://120.25.226.186:32812"; NSString *urlStr = [baseUrlStr stringByAppendingPathComponent:video.image]; [cell.imageView sd_setImageWithURL:[NSURL URLWithString:urlStr] placeholderImage:[UIImage imageNamed:@"qq"]]; // NSLog(@"----%@",video.ID); return cell; } #pragma -mark tableView的代理方法 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { //1. 拿到数据 // NSDictionary *dict = self.videos[indexPath.row]; ZYVideo *video = self.videos[indexPath.row]; //2. 拼接资源路径 NSString *urlStr = [baseUrlStr stringByAppendingPathComponent:video.url]; //3. 创建播放器 MPMoviePlayerViewController *mpc = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:urlStr]]; //4. 弹出控制器 [self presentViewController:mpc animated:YES completion:nil]; } @end