iOS ---解析

2016-05-16  本文已影响451人  PlatonsDream

解析:从事先约定好的格式中提取数据。这种格式是前端开发人员和后台约定好的,约定获取的数据是什么格式的,就是用什么格式的解析方式(一般都是前端开发人员听从后台的)
解析的前提:按照约定好的格式,数据提供方按照格式提供数据、数据获取方按照格式获取数据
解析常见的为XML解析、 JSON解析

JSON解析

{
    "reason":"success",
    "result":[
        {
            "movieId":"216609",
            "movieName":"诡八楼",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583083"
        },
        {
            "movieId":"216391",
            "movieName":"摩登森林之美食总动员",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583246"
        },
        {
            "movieId":"216162",
            "movieName":"龟兔再跑",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583181"
        }
         ......
       ],

"error_code":0
}

上面为JSON格式数据,是一个大字典,字典的键值对中的值又包括数组。数组中又包含好多个字典,每个字典的键值对就是我们需要取出的数据
json文件有两种结构:

对象:"名称/值"对的集合。不同的语言中,它被理解为对象,记录,结构,字典,哈希表,有键列表,或者关联数组。以"{" 开始, 以"}" 结束, 是"名称/值"对的集合。名称和值中间用":"隔开。多个"名称/值"对之间用 ", " 隔开

数组: 值得有序列表。在大部分语言中,它被理解为数组。以"[" 开始, 以"]" 结束,中间是数据。数据以 ", " 分隔

JSON中的数据类型:字符串,数值,BOOL,对象,数组

JSON解析工具:JSONKit、 NSJSONSerialization、 TouchJSON 和SBJSON等,其中NSJSONSerialization是系统提供的解析类,其解析效率是最高的
其中关于其他第三方的JSON解析工具 在http://www.jianshu.com/p/a54d367adb2a 里面会有讲解,这里只是分享了系统自带的JSON解析工具NSJSONSerialization

NSJSONSerialization 解析步骤:

1.得到json文件,并且转换为data类型
step1.1文件路径

NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"MovieList" ofType:@"text"];

step1.2转化为 nsdata类型

NSData *jsonData = [NSData dataWithContentsOfFile:jsonPath];//根据路径获取data类型数据

step1.3解析json 数据 jsonkit sbjson touchjson 三种解析第三方 但是还是系统提供的json解析更好用

NSError *error = nil;
    NSDictionary *resultDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragmentserror:&error];  //系统提供的json解析数据的工具
    //error错误  里面包含了解析是处的错误,一般打印是为了验证错误点
    NSLog(@"%@", error);

2.判断解析获得的数据是否正常(是否是我们想要的数据) //这一步是在验证,真正开发时,可以不使用

if (resultDic) {  //如果解析的数据不为空
        //判断当前的对象是否支持json格式
        if ([NSJSONSerialization isValidJSONObject:resultDic]) {
            NSData *strData = [NSJSONSerialization dataWithJSONObject:resultDic options:NSJSONWritingPrettyPrinted error:nil];
            //将data 转换为字符串
            if (strData != nil) {
                NSString *str = [[NSString alloc] initWithData:strData encoding:NSUTF8StringEncoding];
                NSLog(@"%@", str);
            }
        }
    }

XML解析

<?xml version="1.0" encoding="utf-8"?> <!--此行包含XML的版本信息和编码格式-->
<students><!--这是开始标签,也就是根节点-->
    <student attribute = "七班班宝" position = "bu"><!--student为根节点的子节点,name节点的父节点, attribute是它的属性-->
        <name>赵威</name><!--李帅为name节点的值-->
        <sex>无</sex>
        <age>14</age>
    </student>
    <student attribute = "七班班长">
        <name>鹏鹏</name>
        <sex>随条件改变</sex>
        <age>17</age>
    </student>
    <student attribute = "banzhangtamei">
        <name>lisi</name>
        <sex>随他呢</sex>
        <age>33</age>
    </student>
</students><!--节点的结束标签都是以/加标签名称组成 -->

上面为XML格式数据。
XML: Extensible Markup language (可拓展标记语言),主流数据格式之一,可以用来存储和传输数据
节点:使用一对标签表示:起始和结束标签 <节点名> 数据或其他节点</节点名>
XML数据结构:有且只有一个根节点,如上面代码中的students, 但是在根节点中可以嵌套好多子节点,子节点可以作为父节点嵌套下一级子节点 如<student> <name> </name> </student> student 作为父节点students的子节点,又是name节点的父节点
节点中可以有值,存储在一对标签中 如 <name>赵威</name> 节点的值就是 赵威
这样按照层级的层次把数据存储在节点中,获取数据也是调取节点中的数据

XML解析的作用:数据交换 内容管理 用作配置文件

XML解析又分为SAX解析和DOM解析

XML解析之SAX解析

SAX: Simple API for XML。基于事件驱动的解析方式,逐行进行解析数据(采用协议回调机制)。

SAX解析使用的类:NSXMLParser 。NSXMLPraser是系统自带的XML解析类,采用SAX方式解析数据。
解析过程由NSXMLPraserDelegate协议方法回调
解析过程:开始标签->取值->结束标签->取值

@interface RootViewController ()<NSXMLParserDelegate>//签协议
@property (nonatomic, strong) NSMutableDictionary *dic;//用来student节点中的值
@property (nonatomic ,strong) NSMutableArray *allDataArray;//用来盛放所有的student节点转换的字典
@property (nonatomic, strong) NSMutableString *valueString;//用来拼接节点中间的值
@end
//得到需要解析的数据   获取数据文件所在的地址
    NSString *saxPath = [[NSBundle mainBundle] pathForResource:@"XMLDemo" ofType:@"xml"];
    //获取data
    NSData *saxData = [NSData dataWithContentsOfFile:saxPath];
    //创建sax解析的工具类对象
    NSXMLParser *saxParser = [[NSXMLParser alloc] initWithData:saxData];
    //指定代理
    saxParser.delegate = self;
    //开始解析 sax解析是一个同步的过程
   BOOL isParser = [saxParser parse];
    //判断解析成功
    if(isParser)
        NSLog(@"解析完成");
    else
        NSLog(@"解析失败");
#pragma mark --sax解析代理方法
//开始解析
- (void)parserDidStartDocument:(NSXMLParser *)parser {
     NSLog(@"开始解析");
    //初始化数组(遍历构造器)   在开始解析里面初始化保存数据的数组
    self.allDataArray = [NSMutableArray array];
}

//开始解析某个节点
/*
elementName:标签名称
namespaceURI:命名空间指向的链接
qualifiedName:命名空间的名称
attributtes:节点的所有属性(可以多个)
 */
- (void)parser:(NSXMLParser *)parser didStartElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(nonnull NSDictionary<NSString *,NSString *> *)attributeDict {
    NSLog(@"开始解析%@节点", elementName);
    //当开始解析student子节点的时候,就应该初始化字典,因为一个字典就对应着一个学生的信息
    //每解析一个student,就初始化一次
    if ([elementName isEqualToString:@"student"]) {
        self.dic = [NSMutableDictionary dictionary];
    }
}

//获取节点之间的值
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    NSLog(@"取值---%@", string);
//    if(self.valueString){//说明有值
//        [self.valueString appendString:string];
//    }else{
//        self.valueString = [NSMutableString stringWithString:string];
//    }
    //这里会把空格覆盖掉
    if (string != nil) {
        self.valueString = [NSMutableString stringWithString:string];
    }
    
}

//某个节点结束取值
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    NSLog(@"结束%@节点的解析", elementName);
    
    if ([elementName isEqualToString:@"name"]) {//说明name节点已经取值结束
        [self.dic setObject:self.valueString forKey:elementName];
    }
    if ([elementName isEqualToString:@"age"]) {
        [self.dic setObject:self.valueString forKey:elementName];
    }
    if ([elementName isEqualToString:@"sex"]) {
        [self.dic setObject:self.valueString forKey:elementName];
    }
    
//    [self.dic setObject:self.valueString forKey:elementName];
    
    if ([elementName isEqualToString:@"student"]) {//一个student已经解析完毕
        [self.allDataArray addObject:self.dic]; //把studnet的字典添加到数组中
    }
    self.valueString = nil; 
}

//结束解析 在结束解析协议方法中内获取全部的数据
- (void)parserDidEndDocument:(NSXMLParser *)parser {
    //就可以使用解析完成的数据
    NSLog(@"%@", self.allDataArray);
    NSLog(@"整个解析结束");
}

//报告不可恢复的解析错误
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
    NSLog(@"解析出现错误:%@", parseError);
}

XML解析之DOM解析

DOM: Document Object Model(文档对象类型)。DOM方式解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点数),通过遍历节点树结构可以检索任意XML节点,读取他的属性和值。而且通常情况下,可以借助XPath,直接查询XML节点。
DOM是基于文档的解析方式。

DOM解析需要导入的库 libxml2.dylib(ios7之后改为libxml2.tdb) GDataXMLNode
GDataXMLNode是Google提供的开元XML解析类,对libxml2.tdb进行了Object-C的封装,能对较小或中等的xml文档进行读写操作并且支持XPath语法
使用GDataXMLNode使用方法
1.获取GDataXMLNode.h/m文件,将GDataXMLNode.h/m文件添加到工程中
2.向工程中增加"libxml2.dylib(ios7之后改为libxml2.tdb) "动态库
3.在工程的"Build Settings"页中找到"Header Search Path"项,添加/usr/include/libxml2
4.导入"GDataXMLNode.h"文件到头文件中,如工程能编译通过,则说明GDataXMLNode添加成功

解析过程

//用来盛放所有的字典
    NSMutableArray *datasourse = [NSMutableArray array];
    
    //得到需要解析的数据(xml文件)
    NSString *xmlPath = [[NSBundle mainBundle] pathForResource:@"XMLDemo" ofType:@"xml"];
    //转换为NSData类型
    NSData *xmlData = [NSData dataWithContentsOfFile:xmlPath];
    
    //构建document文档对象
    NSError *error = nil;
    GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];//options:的值为0,这个是预留的
    
    //找到根节点,就是students
    GDataXMLElement *rootElement = [doc rootElement];
    
    //找到根节点的所有子节点,就是所有的student
    NSArray *allSubNotes = [rootElement elementsForName:@"student"];
    //找到student节点的所有子节点
    for (GDataXMLElement *item in allSubNotes) {
        //每次循环开始的时候,说明是一个新的student节点,我们需要字典来盛放他所有的值
        //防止引用计数加一,使用初始化方法
        
        NSLog(@"%@", item.attributes[0]);
        NSMutableDictionary *studentDic = [NSMutableDictionary dictionary];
        
        //得到name节点
        NSArray *nameArray = [item elementsForName:@"name"];
//        GDataXMLElement *nameElement = [nameArray objectAtIndex:0];
        GDataXMLElement *nameElement = [nameArray firstObject];
        //取值
        NSString *name = [nameElement stringValue];
        [studentDic setObject:name forKey:@"name"];
        //取出sex
        NSArray *sexArray = [item elementsForName:@"sex"];
        GDataXMLElement *sexElement = [sexArray firstObject];
        NSString *sex = [sexElement stringValue];
        [studentDic setObject:sex forKey:@"sex"];
        
        //取出age
        NSArray *ageArray = [item elementsForName:@"age"];
        GDataXMLElement *ageElement = [ageArray firstObject];
        //取值
        NSString *age = [ageElement stringValue];
        [studentDic setObject:age forKey:@"age"];
        
        //将字典添加到可变数组中
        [datasourse addObject:studentDic];
    }

SAX解析和DOM解析的区别:

SAX只能读不能写,DOM解析不知能读,还能写(增加节点)
如果文档小一些,DOM解析效率更高一些
DOM解析基于文档,SAX解析基于事件
如果数据量相同时,DOM解析效率更高
SAX解析是逐行解析,DOM解析是整个文档来操作的
数据量比较大时,适用于SAX解析

JSON解析和DOM解析的优缺点

XML优缺点

优点:

1.格式统一,符合标准
2.容易与其他系统进行远程交互,数据共享比较方便

缺点:

1.XML格式文件庞大,格式复杂,传输暂用宽带
2.服务器端和客户端都需要花费大量代码来维护XML,不论服务器端还是客户端都使代码变得异常复杂和不容易维护
3.刻画段不同浏览器之间解析XML的方式不一致,需要重复编写很多代码
4.服务器端和客户端解析MXL花费资源和时间

JSON优缺点
优点:

1.数据格式比较简单,易于读写,格式都是压缩的,占用带宽小。
2.易于解析这种语言。
3.支持多种语言,包括ActionScrip, C, C#, ColdFusion, Java, JavaScript, Perl, PHP, Python, Ruby等语言服务器端语言,便于服务器端的解析
4.因为JSON格式能够直接为服务器端代码使用,大大简化了服务器端和客户端的代码开发量,大师完成的任务不变,且易于维护。

缺点:

1.没有XML格式这么推广的深入人心和使用广泛,没有XML那么通用性。
2.JSON格式目前在Web Service中推广还属于初级阶段

比较 :

xml在布局文件比json强太多,但是json更便于传输
xml是可拓展的语言,随便往里面添加标签,标签名字可以随便改变

上一篇下一篇

猜你喜欢

热点阅读