iOS基础-数据解析方法初步总结-(XML,JSON欢迎指正)

小时候的记忆与大家一起分享,愿君安好!
  • 解析的基本概念

  • 解析: 从事先规定好的格式中提取数据
  • 解析的前提: 提前约定好格式,数据提供方按照格式提供数据,数据获取方则按照格式获取数据 OS开发常见的解析: XML解析,JSON解析


XML_stu.txt在我们的工程中引入要解析的文件这个只是一个简单例子(根据数据创建并引入一个Student类去处理数据)

XML解析 :

  • 可拓展标记语言 (eXtensible Markup Language)

XML数据格式的功能:

1 : 数据交换
2 : 内容管理
3 : 用作配置文件

XML数据结构的语法

1 : 文档声明 --在 XML文档在最前面必须写一个文档声明.

  • 1.1 简单的文档声明 : <?xml version="1.0"?>
  • 1.2 用 encoding 属性, 来说明文档字符编码 :<?xml version="1.0" encoding="UTF-8">

2 : (元素 Element)节点使用一对标签表示:起始和结束标签

  • (1)有元素内容:<name>你</name>
  • (2)无元素内容:<name></name> 而且一个元素可以嵌套若干个子元素,但不能出现交叉嵌套

3 : 根节点是起始节点,只有一个,节点可以嵌套
4 : 节点可以有值,存储在一对标签中.
5 : 规范的 XML 文档最多只有一个根元素, 其他的都是根元素的子孙元素;
6 : 在XML中, 空格和换行,都会被当做具体的内容去处理;
7 : 属性 (Atribute) : 一个元素可以拥有多个属性,例如 <video name="小黄人" hobby="banana"/> [video元素拥有name, hobby两个属性]

  • (1): 属性的值必须使用""或者''括住
  • (2): 属性表示的信息也可以用子元素来表示,例如:
    <video>
    <name>小黄人</name>
    <hobby>banana</hobby>
    </video>

解析方式,逐行进行解析

1:打开XML文档
2: 开始节点 (开始标签)
3: 发现元素里面的内容
4: 结束节点 (结束标签)
5: 循环开始, 直到遇到</persons>解析才彻底结束

iOS中XML解析方式有很多

1: 苹果原生:NSXMLParser --SAX方式解析,使用简单
2: 第三方框架:
(1)libxml2 : 纯C语言,默认被包含进了iOS SDK, 同时支持DOM 和 SAX 解析
(2)GDataXMl: DOM的解析方式, 是由谷歌开发的, 底层基于libxml2

  • 第一种 : SAX解析 (系统自带的XML方法)

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

1 : NSXMLParser: NSXMLParser是iOS自带的XML解析类,采用SAX方式解析数据
2 : 解析过程由NSXMLParserDelegate协议方法回调
3 : 解析过程: 开始标签-> 取值(model赋值) -> 结束标签 ->取值(这个时候我们要了解是否要还给我们model赋值)

  • 要使用iOS中系统的SAX解析 需要遵守 NSXMLParserDelegate 协议
    @interface ViewController ()<NSXMLParserDelegate>
  • 声明属性 数据源数组 用于存储解析数据给你使用
    @property (nonatomic, strong) NSMutableArray *data;
  • 声明一个用于存储当前的标签名字的属性 (后面具体使用)
    @property (nonatomic, copy) NSString *currentElement;
  • 在一个触发的行为里面开始实现数据解析我这里在一个控制器里面使用点击方法

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// [NSBundle mainBundle] 代表的是你的应用包(其实就是你Xcode左面的那个文件夹栏)
// [pathForResource:@"文件名" ofType:@"文件格式"];
NSString *path = [[NSBundle mainBundle] pathForResource:@"XML_stu" ofType:@"txt"];
// 通过文件路径 创建一个NSData对象
NSData *data = [NSData dataWithContentsOfFile:path];
// SAX解析使用类

 parser.delegate = self;```
// 开始解析  执行这个方法
```   [parser parse];```
}

- ###执行代理方法
- ####第一步 : 开始解析文档
// 1 : 开始解析文档  
```- (void)parserDidStartDocument:(NSXMLParser *)parser
{
//我们需要解析文档了 就需要自己保存解析的数据  在这里初始化数据源数组
 self.data = [NSMutableArray array];
}```

- ####第二步 : 检测到开始标签
-  // 第一个参数:类
- // 第二个参数: elementName 标签的名字
- // 以下三个基本为nil,一般不会使用
- // 第三个参数: 节点里面的命名空间(xmlns)
- // 第四个参数: qName 这个我还没弄明白 大家谁知道可以帮助一下 等我知道来修改
- // 第五个参数: attributeDict 标签的属性
// 2 : 检测到开始标签

> 
```code
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict
{// 给currentElement 赋值 这个属性就是记录每次的检测的开始标签(其实目的就是对应的Student的属性去给model赋值)
 self.currentElement = elementName;
// 如果标签的名字是student 则表示 要创建model(这里就是Student类实例对象)  并添加到数据源数组
 if ([elementName isEqualToString:@"student"])
 {
     Student *model = [Student new];
     [self.data addObject:model];
 }
 NSLog(@"<开始标签名>== %@", elementName);  
}
  • 第三步 : 检测到标签的值 * ( 这一步 : 我的理解是 当找到不管是开始标签还是结束标签都回去找标签的对应值 所以在后面的第四步 需要让 self.currentElement = nil 不然结束标签对应\n 也是说没有值 那么导致又一次走给Model赋值结果Model值就没有给对给成了对应的结束标签的一般空值 我们要的是开始标签对应的值所以这样操作)*

  • // 第一个参数 : 类
  • // 第二个参数 : 对应的标签下的值
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
//  将检测到的值 存入Model的具体属性(*根据获取的标签的名字通过KVC赋值*)
//  给数组的最后的 model赋值
  [[self.data lastObject] setValue:string forKey:self.currentElement];
  NSLog(@"<string值=> == %@ ", string);
  NSLog(@"<key=> == %@",self.currentElement);
}```

- ###第四步 : 检测到结束标签
// 4 : 检测到结束标签

>```obj
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
// 这里上面已经说过结束标签找到后依然会走第三步去赋值   所以我们让Key为空就不会把我们已经存在的值去改掉了
    self.currentElement = nil;
    NSLog(@"<结束标签>== %@", elementName);
}
  • 第五步 : 结束解析文档

// 5 : 结束解析文档 (这里你可以做一些操作,比如打印你的数据源数组看看数据解析是否成功 我这里的Student类重写了description方法可以直接打印看到数据不然看到地址)

  • (void)parserDidEndDocument:(NSXMLParser *)parser
    {
    for (Student *stu in self.data)
    {
    NSLog(@"%@",stu);
    }
    }```


  • 第二种方法 : DOM工具:(谷歌公司封装的OC代码块 第三方工具)

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

  • GDataXMLNode :

1 : 采用DOM方式解析数据
2 : iOS包含一个C语言的动态链接库libxml2.tbd,解析熟读比NSXMLParser快.
3 :GDdataXMLNode是Google提供的XML解析类, 对libxml2.tbd(xcode7以前是 .dylib)进行了Objective-C的封装,能对较小或中等的xml文档进行读写操作且支持Path语法.

  • 使用方法:

1 : 获取GDataXMLNode.h /.m 文件,将GDataXMLNode.h /.m文件添加到工程中
2 : 向工程中增加”libxml2.tbd”动态库
3 : 在工程的”Build Settings”页中找到”Header Search Path”项,添加 "/usr/include/libxml2 "
4 : 导入”GDataXMLNode.h / .m” 文件到头文件中,如工程能编译通过,则说明GDataXMLNode添加成功.

属性和方法:



  • 这个代码较少我直接把整个.m放上供参考

#import "Vc2ViewController.h"
#import "GDataXMLNode.h"
#import "Student.h"
@interface Vc2ViewController ()
//数据源数组
@property (nonatomic, strong) NSMutableArray *dataArray;
@end

@implementation Vc2ViewController

    [super viewDidLoad];}```

```obj
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    self.dataArray = [NSMutableArray array];
    NSString *path = [[NSBundle mainBundle] pathForResource:@"XML_stu" ofType:@"txt"];
   NSData *data = [NSData dataWithContentsOfFile:path];
   NSError *error = nil;```
    // GDataXMLDocument  XML的DOM解析使用的类
    // 第一个参数 : 解析的data对象
    // 第二个参数 : 一般就是0
    // 第三个参数 : error信息
  ```  GDataXMLDocument *document = [[GDataXMLDocument alloc] initWithData:data options:0 error:&error];```
   ///获取到根节点里面所有的东西,也就是说获取到students里面包含的所有东西
  ```obj
  GDataXMLElement *rootElment = [document rootElement];
    NSLog(@"<rootElement == > == %@",rootElment);
    for ( GDataXMLElement *subElement in rootElment.children)
    {
        // 在这获取到的subElement保存的是student标签里面的内容,所以这里创建对象
        Student *student = [Student new];
        [self.dataArray addObject:student];
           for (GDataXMLElement *element in subElement.children)
        {
            //  element 保存的就是student标签的所有子标签
            // 根据标签的名字给 属性赋值
            // element.name 标签的名字
            // element.stringValue 标签的值
// 第一种赋值方法: 逐一对应属性赋值
            if ([element.name isEqualToString:@"name"])
            {
                student.name = element.stringValue;
            }
            if ([element.name isEqualToString:@"gender"])
            {
                student.gender = element.stringValue;
            }
            if ([element.name isEqualToString:@"hobby"])
            {
                student.hobby = element.stringValue;
            }
            if ([element.name isEqualToString:@"age"])
            {
                student.age = [element.stringValue integerValue];
            }

// 第二种: 赋值方法 setValue 的方法赋值更简单: (2 选 1 即可 )
            [stu setValue:tempE.stringValue forKey:tempE.name];
        }
        NSLog(@"<subElement>==%@",subElement);
        for (Student *stu in self.dataArray)
        {
            NSLog(@"<学生>= %@",stu);
        }
}
}```
___
____

- #XML的优缺点: 
  -  优点 : 
1 : 格式统一,符合标准
2 : 容易与其他系统进行远程交互,数据共享比较方便

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

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


- ###JSON文件有两种结构: 
> - 对象: “名称/值” 对的集合 .不同的语言中,它被理解为对象,记录, 结构, 字典, 哈希表, 有键列表, 或者关联数组. 以 ” {“ 开始,以 “}” 结束, 是”名称/值” 对的集合.  名称和值中间用 “:” 隔开, 多个 “名称/值” 对之间用 “,” 隔开 .
 - 数组: 值的有序列表. 在大部分语言中, 它被理解为数组 . 以 “[“ 开始, 以 ”]” 结束, 中间是数据. 数据已 “,” 分隔.
 -  JSON中的数据类型 : 字符串, 数值 ,BOOL, 对象,数组

![举例](http://upload-images.jianshu.io/upload_images/1523603-219928ee8be06d44.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

- ##功能: 
>- ###数据交换
 - ###内容管理
 - ###配置文件



![引入这个我们需要解析的数据 JSON_stu.txt](http://upload-images.jianshu.io/upload_images/1523603-2417bb8b68e61249.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- ##NSJSONSerialization工具:(系统自带的)
> ````- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{````
   //获取文件路径
   ```` NSString *path = [[NSBundle mainBundle]pathForResource:@"JSON_stu" ofType:@"txt"];````
//创建数据对象 
```` NSData *data = [NSData dataWithContentsOfFile:path];  ````
  //   NSJSONReadingMutableContainers  返回一个数组或者字典
//    NSJSONReadingMutableLeaves  返回一个字符串
//    NSJSONReadingAllowFragments 返回一个任意类型的对象 (既可以是字典也可以是数组或者字符串 只要是 JSON 有效数据片段)
//  将json数据转化成需要的格式
   ```code
 NSArray *array = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingAllowFragments error:nil];
    NSLog(@"array --> %@",array);
for (NSDictionary *dict in array) 
{ 
NSLog(@"dict --> %@",[dict objectForKey:@"content"]);
}   
}````
____
____

- ##JSONKit工具:(第三方工具)
- 首先要引入第三方框架(JSONKit到你的工程)用这个第三方就简单了许多但是需要引入也是蛮麻烦,有时候还要设置你的编码,因为JSONKit实在mrc下的可以这样来改
![JSON解析配置Build Phases](http://upload-images.jianshu.io/upload_images/1523603-be1f0983800f83bc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


- 解析方法实现(还是比较好记忆的吧)

> ```obj
- (void)touchesBegan:(NSSet<UITouch*> *)touches withEvent:(UIEvent*)event
{      
NSString*path = [[NSBundlemainBundle]pathForResource:@"JSON_stu" ofType:@"txt"];   
NSData*data = [NSDatadataWithContentsOfFile:path];   
//将json数据转化成需要的格式  
 NSArray*array = [data  objectFromJSONData];     
 NSLog(@"array ---> %@",array);  
 }```


- ##JSON优缺点:

> ##优点: 
1. 数据格式比较简单,易于读写,格式都是压缩的,占用带宽小.
2. 易于解析这种语言
3. 支持多种语言,包括ActionScript ,C, C#, ColdFusion, Java, JavaScript, Perl, PHP, Python, Ruby等语言服务器端语言,便于服务器端的解析
4. 因为JSON格式能够直接为服务器端代码使用, 大大简化了服务器端和客户端的代码开发量,但是完成的任务不变, 且易于维护.
> ##缺点:
1. 没有XML格式这么推广的深入人心和使用广泛,没有XML的通用性!
2. JSON格式目前在Web Service中推广还属于初级阶段
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 解析的概念 解析:从事先规定好的格式中提取数据。 解析的前提:提前约定好格式,数据提供方按照格式提供数据,数据获取...
    逗逗豆豆笑阅读 1,108评论 2 14
  • JSON JSON和XML都是需要解析的 JSON是一种轻量级的数据格式,一般用于数据交互服务器返回给客户端的数据...
    JonesCxy阅读 1,760评论 2 10
  • 在网络开发中,从服务器获取的二进制数据包括: > html >图片 >视频 >音频 > zip等 除了以上文件格式...
    小番茄阳阳阅读 742评论 0 0
  • 在网络开发中,从服务器获取的二进制数据包括: > html > 图片 > 视频 > 音频 > zip 等 除了以上...
    方圆十里不留母狗阅读 763评论 0 0
  • 在工作中,不可避免的我们会频繁从网络获取XML或者Json格式的数据,这些数据有着特定的数据结构,必须对其进行解析...
    Elbert_Z阅读 857评论 0 2