网络篇 - 05.网络数据解析(XML)

来源:互联网 发布:同花顺炒股软件 编辑:程序博客网 时间:2024/06/06 04:13

1.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>

2.XML语法概述

  • 一个常见的XML文档一般由以下部分组成
    • 文档声明
    • 元素(Element)
    • 属性(Attribute)
  • XML语法 – 文档声明
    • 在XML文档的最前面,必须编写一个文档声明,用来声明XML文档的类型
//最简单的声明,声明版本信息<?xml version="1.0" ?>//用encoding属性说明文档的字符编码信息<?xml version="1.0" encoding="UTF-8" ?>
  • XML语法 – 元素(Element)
    • 一个元素包括了开始标签和结束标签
      • 拥有内容的元素:小黄人
      • 没有内容的元素:
      • 没有内容的元素简写:
    • 一个元素可以嵌套若干个子元素(不能出现交叉嵌套)
    • 规范的XML文档最多只有1个根元素,其他元素都是根元素的子孙元素
<videos>    <video>        <name>小黄人 第01部</name>          <length>30</length>    </video></videos>
  • XML语法 –元素的注意
    • XML中的所有空格和换行,都会当做具体内容处理
    • 下面两个元素的内容是不一样的
      • 第1个<video>小黄人</video>
      • 第2个
        <video>
        小黄人
        </video>
  • XML语法 – 属性(Attribute)
    • 一个元素可以拥有多个属性
    • video元素拥有name和length两个属性
    • 属性值必须用 双引号”” 或者 单引号” 括住
<video name="小黄人 第01部" length="30" />//实际上,属性表示的信息也可以用子元素来表示,比如<video>    <name>小黄人 第01部</name>        <length>30</length></video>

3.XML解析

  • 要想从XML中提取有用的信息,必须得学会解析XML

    • 提取name元素里面的内容
      <name>小黄人 第01部</name>
    • 提取video元素中name和length属性的值
      <video name="小黄人 第01部" length="30" />
  • XML的解析方式有2种

    • DOM:一次性将整个XML文档加载进内存,比较适合解析小文件
    • SAX:从根元素开始,按顺序一个元素一个元素往下解析,比较适合解析大文件
  • 在iOS中,解析XML的手段有很多

    • 苹果原生NSXMLParser:SAX方式解析,使用简单
    • 第三方框架libxml2:纯C语言,默认包含在iOS SDK中,同时支持DOM和SAX方式解析
    • GDataXML:DOM方式解析,由Google开发,基于libxml2的封装
  • XML解析方式选择

    • 大文件:NSXMLParser
    • 小文件:GDataXML、NSXMLParser

4.SAX解析-NSXMLParser

  • NSXMLParser
    • 1.传入XML数据,创建解析器
    • 2.设置代理,监听解析过程
    • 3.开始解析
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];parser.delegate = self;[parser parse];
  • NSXMLParser采取的是SAX方式解析,特点是事件驱动,下面情况都会通知代理
    • 当扫描到文档(Document)的开始与结束
    • 当扫描到元素(Element)的开始与结束
  • 常见代理方法(NSXMLParserDelegate)
//当扫描到文档的开始时调用(开始解析)- (void)parserDidStartDocument:(NSXMLParser *)parser//当扫描到文档的结束时调用(解析完毕)- (void)parserDidEndDocument:(NSXMLParser *)parser//当扫描到元素的开始时调用(attributeDict存放着元素的属性)- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict// 当扫描到元素的结束时调用- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
  • 解析实例
    这里写图片描述
    这里写图片描述
#import "ViewController.h"#import "NSString+SandboxPath.h"#import <SDWebImage/UIImageView+WebCache.h>#import <MediaPlayer/MPMoviePlayerViewController.h>@interface ViewController ()<NSXMLParserDelegate>@property (nonatomic, strong) NSMutableArray *videos;// 视频信息@end@implementation ViewController#pragma mark - 懒加载-(NSMutableArray *)videos{    if (!_videos) {        _videos = [NSMutableArray array];    }    return _videos;}- (void)viewDidLoad {    [super viewDidLoad];    self.tableView.rowHeight = 150;    // 1.获取网络数据    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];    NSURLRequest *request = [NSURLRequest requestWithURL:url];    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {        // 2.解析XML数据        // 2.1创建解析器        NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];        // 2.2设置代理        parser.delegate = self;        // 2.3开始解析        [parser parse];    }];}#pragma mark - NSXMLParserDelegate// 只要开始解析XML文档就会调用-(void)parserDidStartDocument:(NSXMLParser *)parser{    NSLog(@"%s",__func__);}// 只要解析完毕XML文档就会调用-(void)parserDidEndDocument:(NSXMLParser *)parser{    NSLog(@"%s",__func__);    // 刷新UI    [self.tableView reloadData];}// 当扫描到元素的开始时调用/* 参数解释: elementName:元素名称 attributeDict:元素中的属性 namespaceURI和qualifiedName是XML DOM的属性,基本用不上 */-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{    NSLog(@"%s",__func__);    if ([elementName isEqualToString:@"videos"]) return;    [self.videos addObject:attributeDict];    NSLog(@"%@",attributeDict);}// 当扫描到元素的结束时调用-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{        NSLog(@"%s",__func__);}// 解析发生错误时调用-(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{    NSLog(@"%s",__func__);}#pragma mark - UITableViewDataSource-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{    return self.videos.count;   }-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    //    1.创建cell    static NSString *identifier = @"cell";    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];    //    2.设置cell的数据    NSDictionary *dict = self.videos[indexPath.row];    cell.textLabel.text = dict[@"name"];    cell.detailTextLabel.text = [NSString stringWithFormat:@"%@",dict[@"length"]];    NSString *urlStr =[NSString stringWithFormat:@"http://120.25.226.186:32812/%@", dict[@"image"]];    urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];    NSURL *url = [NSURL URLWithString:urlStr];    [cell.imageView sd_setImageWithURL:url placeholderImage:nil];    //    3.返回cell    return cell;}#pragma mark - UITableViewDelegate// 选中某一行后播放视频-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{    // 获取视频URL    NSDictionary *dict = self.videos[indexPath.row];    NSString *urlStr =[NSString stringWithFormat:@"http://120.25.226.186:32812/%@", dict[@"url"]];    urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];    NSURL *url = [NSURL URLWithString:urlStr];    // 加载视频播放控制器    MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc] initWithContentURL:url];    // 显示控制器    [self presentViewController:vc animated:YES completion:nil];}

5.DOM解析-NSXMLParser

  • 由于GDataXML基于libxml2库的,而且是MRC的,所以需要在使用GDataXML的项目中做以下配置
  • 导入libxml2库
    这里写图片描述
  • 设置libxml2的头文件搜索路径
    这里写图片描述
  • 设置链接参数(自动链接libxml2库)
    这里写图片描述
  • 由于GDataXML是非ARC的,因此得设置编译参数
    这里写图片描述
  • DOM解析实例(以此前SAX解析的例子)
    // 1.获取网络数据    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];    NSURLRequest *request = [NSURLRequest requestWithURL:url];    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {        // 2.解析XML数据(DOM)        // 2.1创建解析器        GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil];        // 2.2 获取根元素        GDataXMLElement *rootElement = [doc rootElement];        // 2.3从根元素中获取所以子元素        NSArray *elementArr = [rootElement elementsForName:@"video"];        // 2.4遍历数组将数组中的根元素转换为字典(模型)        for (GDataXMLElement *element in elementArr) {            NSMutableDictionary *video = [NSMutableDictionary dictionary];            video[@"id"] = @([element attributeForName:@"id"].stringValue.integerValue);            video[@"image"] = [element attributeForName:@"image"].stringValue;            video[@"url"] = [element attributeForName:@"url"].stringValue;            video[@"name"] = [element attributeForName:@"name"].stringValue;            video[@"length"] = @([element attributeForName:@"length"].stringValue.integerValue);            [self.videos addObject:video];        }        // 2.5 刷新数据        [self.tableView reloadData];    }];}

6.XML和JSON对比

  • 同一份数据,既可以用JSON来表示,也可以用XML来表示
  • 相比之下,JSON的体积小于XML,所以服务器返回给移动端的数据格式以JSON居多
  • 目前市面上80%以上的网络数据都是JSON格式的,但是我们最终还是要看公司后台返回的是哪种格式的数据,根据接口文件解析对应数据即可
0 0
原创粉丝点击