iOS进阶第四天(xml解析与json解析)

解析的概念

  • 解析:从事先规定好的格式中提取数据。
  • 解析的前提:提前约定好格式,数据提供方按照格式提供数据,数据获取方则按照格式获取数据

XML数据结构

  • XML:Extensible Markup language(可扩展标记语言),主流的数据格式之一,可以用来存储和传输数据。

XML数据格式的功能

  • XML解析工具(NSXMLParser,GDataXMLNode,TochXML,KIssXml)
  • 数据交换
  • 内容管理
  • 用作配置文件

XML数据结构的语法

  • 声明
  • 节点使用一对标签表示:起始和结束标签
  • 根节点是起始节点,只有一个,节点可以嵌套
  • 节点可以有值,存储在一对儿标签中

XML数据格式之SAX解析

  • SAX:Simple API for XML.基于时间驱动的解析方式,逐行解析数据。(采用协议回调机制)
  • NSXMLParser类 :1.NSXMLParser是iOS自带的XML解析类,采用SAX方式解析数据。2解析过程由NSXMLParserDelegate协议方法回调。3解析过程:开始标签-->取值-->结束标签-->取值
初始化NSXMLParser.png
NSXMLParserDelegate代理方法.png
NSXMLParserDelegate代理方法2.png

XML值SAX解析实例

  • 要解析的XML文件内容
<?xml version="1.0" encoding="UTF-8"?>
<!-- 根节点 是所有节点的父节点 -->
<!-- 开始节点 -->
<students>  
  <!-- students的子节点  position是该节点属性-->
  <student posotion="愤青">
      <!-- student的  lyj是name标签的内容 我们可以将该节点的所有特性用属性来表示,但是为了阅读起来方便,我们一般也会将该节点的特性用它的子节点来表示-->
      <name>lyj</name>
      <age>25</age>
      <gender>男</gender>
  </student>
  <student posotion="笑星">
      <name>lxf</name>
      <age>23</age>
      <gender>男</gender>
  </student>
<!-- 结束节点 -->
</students>
  • 解析过程
//sax解析:基于事件驱动的解析方式,逐行解析
  //要解析的文件
  NSString *xmlPath = [[NSBundle mainBundle] pathForResource:@"llf" ofType:@"xml"];
  NSString *xmlString = [NSString stringWithContentsOfFile:xmlPath encoding:NSUTF8StringEncoding error:nil];
  //字符串转data
  NSData *xmlData = [xmlString dataUsingEncoding:NSUTF8StringEncoding];
  //参数:需要解析的文件内容
  NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
  //设置代理
  parser.delegate = self;
  //开始解析  这是一个同步的过程(解析完成的时候才会执行下一行代码)
  BOOL isSuccess = [parser parse];
  if (isSuccess) {
      NSLog(@"解析成功");
  }else{
      NSLog(@"解析失败");
  }
  //解析的过程不结束,就不会执行该打印
  NSLog(@"我在解析的最底下");
  NSLog(@"%@",self.allDataMArray);
  • SAX解析类NSXMLParser的代理方法
//开始解析整个文档
- (void)parserDidStartDocument:(NSXMLParser *)parser{
  //初始化外部的可变数组,准备存放解析好的student节点
  self.allDataMArray = [[NSMutableArray alloc] init]; 
}
//当碰到开始节点或者开始标签的时候会执行的代理方法
//elementName:标签名称
//namespaceURI:命名空间  例如 :<teacher xmlns:l="www.lanou3g.com">  namespaceURI就是 l
//qualifiedName:命名空间的值(限制),就是上面的www.lanou3g.com
//attributeDict:标签的属性 例如:<student posotion="愤青"> 
//position就是标签的属性  attributeDict == {position:@"愤青"}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{
  //当开始解析student节点的时候,说明我们要用到一个新的字典了,就需要初始化
  if ([elementName isEqualToString:@"student"]) { 
      self.studentDic = [[NSMutableDictionary alloc] init]; 
  }
  NSLog(@"碰到开始标签-----%@",elementName);
  NSLog(@"--------%@",[attributeDict objectForKey:@"posotion"]);
}
//取出标签中的值
//string:标签中的值
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
  //将节点的内容存储起来,以供节点解析结束使用
  self.noteValueString = string;
  NSLog(@"正在解析的标签的值为-----%@",string);
}
//遇到当前正在解析的标签的结束标签
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
  if ([elementName isEqualToString:@"name"]) {
      //说明name标签解析完成
      [self.studentDic setObject:self.noteValueString forKey:elementName];
  }else if ([elementName isEqualToString:@"age"]){
      [self.studentDic setObject:self.noteValueString forKey:elementName];
  }else if ([elementName isEqualToString:@"gender"]){
      [self.studentDic setObject:self.noteValueString forKey:elementName];
  }
  if ([elementName isEqualToString:@"student"]) {
      //说明一个student已经解析完成
      [self.allDataMArray addObject:self.studentDic];
  }
  NSLog(@"%@标签已经解析结束",elementName);
}
//整个文档解析结束
- (void)parserDidEndDocument:(NSXMLParser *)parser{
  //当整个文档解析结束,说明所有的数据我们已经拿到,可以正常使用了
}
//当解析出错的时候执行的代理方法
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
  NSLog(@"解析出现错误----%@",parseError.description);
}

XML解析之DOM解析(基于文档驱动)

  • DOM解析:DOM:Document Object Model(文档对象模型)。DOM方式解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过遍历树结构可以检索任意XML节点,读取它的属性和值。通常情况下,可以借助XPath,直接查询XML节点。
  • GDataXMLNode
    • 采用DOM方式解析数据
    • iOS中包含一个C语言的动态链接库libxml2.dylib(Xcode7以后改为libxml2.tbd),解析速度比NSXMLParser快
    • GDataXMLNode是Google提供的开源XML解析类,对libxml2.tbd进行了Objecttive-C的封装,能对较小或中等的xml文档进行读写操作且支持XPath语法。
  • GDataXMLNode使用方法
    • 获取GDataXMLNode。h/m文件,将其添加到工程中
    • 向工程中增加libxml2.tbd动态库
    • 在项目的“Build Settings”页中找到“Header Search Path”项,添加“/usr/include/libxml2”
    • 导入“GDataXMLNode.h”文件到头文件中,如果项目能编译通过,则说明GDataXMLNode添加成功
GDataXMLElement类的方法.png
  • XML之DOM解析之GDataXMLNode解析实例
//需要获取解析的源文件
  NSString *xmlPath = [[NSBundle mainBundle] pathForResource:@"llf" ofType:@"xml"];
  NSString *xmlString = [NSString stringWithContentsOfFile:xmlPath encoding:NSUTF8StringEncoding error:nil];
  //字符串转data
//    NSData *xmlData = [xmlString dataUsingEncoding:NSUTF8StringEncoding];
//dom解析
  //第一步:将源xml文件转换成树状结构的文档放在内存中,以供遍历获取每个节点
  GDataXMLDocument *xmlDocment = [[GDataXMLDocument alloc] initWithXMLString:xmlString encoding:NSUTF8StringEncoding error:nil]; 
  //第二步。获取根节点,相当于获取到了students节点
  GDataXMLElement *rootElement = [xmlDocment rootElement]; 
  //初始化一个可变数组,准备存放所有的student装换成的子典
  NSMutableArray *allStudentArray = [[NSMutableArray alloc] init];
  //向现有的文档动态的增加一个student节点
  //相当于创建了一个   <student></student>
  GDataXMLElement *newstudentElement = [GDataXMLElement elementWithName:@"student"];
  GDataXMLElement *nameElement = [GDataXMLElement elementWithName:@"name" stringValue:@"lb"];
  GDataXMLElement *ageElement = [GDataXMLElement elementWithName:@"age" stringValue:@"25"];
  GDataXMLElement *genderElement = [GDataXMLElement elementWithName:@"gender" stringValue:@"man"];
   //为student增加子节点
  [newstudentElement addChild:nameElement];
  [newstudentElement addChild:ageElement];
  [newstudentElement addChild:genderElement];
  //将student节点加入到他的父节点中
  [rootElement addChild:newstudentElement];
//第三步,获取我们需要的子节点 参数是我们需要获取的
 NSArray *studentArray =[rootElement elementsForName:@"student"];
//第四步;遍历studentArray
//studentNode  对应一个student节点
  /*
   <student>
      <age></age>
      <name></name>
      <gender></gender>
  </student>
   */
//    for (GDataXMLElement *studentNode in studentArray) {
//        
//        //初始化一个字典
//        NSMutableDictionary *studentDic = [[NSMutableDictionary alloc] init];
//        //取值
//        NSString *name = [[studentNode elementsForName:@"name"].firstObject stringValue];
//        NSString *age = [[studentNode elementsForName:@"age"].firstObject stringValue];
//        NSString *gender = [[studentNode elementsForName:@"gender"].firstObject stringValue];      
//        //给字典设置值
//        [studentDic setObject:name forKey:@"name"];
//        [studentDic setObject:age forKey:@"age"];
//        [studentDic setObject:gender forKey:@"gender"];
//        //字典放到数组中
//        [allStudentArray addObject:studentDic];
//    }
for (GDataXMLElement *studentNode in studentArray) {
      //遍历获取student所有的子节点
      NSArray *subStudnetNodeArray = [studentNode children];
      NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
      for (GDataXMLElement *subOfStudentNode in subStudnetNodeArray) {
          //获取子节点的名称
          NSString *nodeName = [subOfStudentNode name];
          NSString *nodeValue = [subOfStudentNode stringValue];
          [dic setValue:nodeValue forKey:nodeName];
      }
      [allStudentArray addObject:dic];
  }
  self.student.text = string;
  NSLog(@"%@",allStudentArray);

Json解析

  • JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,JSON采用完全独立于语言的文本格式,易于阅读和编写,同时也易于机器解析和生成。这些特性使JSON成为理想的数据交换语言。

  • JSON文件有两种结构:1.对象;2.数组

  • JSON解析工具:JSONKit,NSJSONSerialization(系统类,iOS5.0之后出现的),TouchJSON,SBJSON等

  • json解析实例

NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"data" ofType:@"json"];
NSString *jsonString = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
//json解析
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"%@",dic);


![NSJSONSerialization类的两个方法.png](http://upload-images.jianshu.io/upload_images/3403981-7a51791c03996fa8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


####总结
**XML优缺点:**
- 优点:
  1.格式统一,符合标准。
  2.容易与其他系统进行远程交互,数据共享比较方便
- 缺点:
  1.XML文件格式庞大,格式复杂,传输占用带宽
  2.服务器和客户端都需要花费大量代码来解析XML,不论服务器端还是客户端都使代码变得异常复杂和不容易维护。
  3.客户端不同浏览器之间解析XML的方式不一致,需要重复编写很多代码。
  4.服务器端和客户端解析XML花费资源和时间。
**JSON优缺点:**
- 优点:
  1.数据格式比较简单,易于读写,格式都是压缩的,占用带宽小。
  2.这种语言易于解析。
  3.支持多种语言,包括ActionScript,C,C#,ColdFusion,Java,JavaScript,Perl,PHP,Python,Ruby等服务器端语言,便于服务器端解析。
  4.因为JSON格式能够直接为服务器端代码使用,大大简化了服务器端和客户端的代码开发量,但是完成的任务不变,且易于维护。
- 缺点
  1.没有XML格式折这么推广的深入人心和广泛使用,没有XML那么通用
  2.JSON格式目前在Web Service中的推广还属于初级阶段




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

推荐阅读更多精彩内容