美文网首页Network我爱编程
iOS进阶第四天(xml解析与json解析)

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

作者: 逗逗豆豆笑 | 来源:发表于2016-12-19 20:47 被阅读236次

    解析的概念

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

    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:https://img.haomeiwen.com/i3403981/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中的推广还属于初级阶段
    
    
    
    
    

    相关文章

      网友评论

      • 秦子帅:我写的键盘放心用。肯定不出错。 希望哥们star一下。 哥们

      本文标题:iOS进阶第四天(xml解析与json解析)

      本文链接:https://www.haomeiwen.com/subject/rqwtvttx.html