iOS ---解析
解析:从事先约定好的格式中提取数据。这种格式是前端开发人员和后台约定好的,约定获取的数据是什么格式的,就是用什么格式的解析方式(一般都是前端开发人员听从后台的)
解析的前提:按照约定好的格式,数据提供方按照格式提供数据、数据获取方按照格式获取数据
解析常见的为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是可拓展的语言,随便往里面添加标签,标签名字可以随便改变