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是可拓展的语言,随便往里面添加标签,标签名字可以随便改变

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容