IOS--UI--LessonParse 数据解析 XML JSON

一 什么是解析?
1.解析:按照约定好的格式提取数据 就是解析
2.数据的提供方:后台开发人员 按照约定好的格式存入数据
数据的提取方:按照约定好的格式提出数据
3.目前主流格式:XML/JSON

① XML 以标签的形式 管理数据 使用比较长的一种方式 比较复杂 逐渐被代替中
/*
1.标签包括:开始标签 结束标签,一对开始和结束标签叫节点;
2.没有父节点的节点叫做根节点,没有子节点的节点叫做叶子节点;我们要取的数据一般都在叶子节点里
3.解析的两种形式:
3.1 SAX 解析 (适合解析大数据 大数据喜欢吃内存 ) NSXMLParser
基于事件回调的形式解析,自己不想做 让别人做就是回调 找代理 ,逐行解析 系统提供的就是这样的
优点:对内存占有率较低
缺点:效率低 适合大数据

3.2 DOM 解析
解析时,会把数据解析到内存中,把读入的数据初始化成树状结构,然后一层一层的读取,适用于小数据 谷歌提供的 GDataXMLNode
*/
②JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与客户端的交互 ,逐渐代替 XML

二 XML
1. 首先看一下 xml 的 数据源

<?xml version = "1.0" encoding = "UTF-8"?>
<lanou27>// 开始标签
    <Student position = "团一波"> //开始标签
        <name>Nyx</name>
        <gender>Girl</gender>
        <age>18</age>
        <say>我们来吧</say>
    </Student>//结束标签
    <Student position = "等我大招">//开始标签
        <name>Sona</name>
        <gender>Girl</gender>
        <age>18</age>
        <say>我不会说话啊</say>
    </Student>//结束标签
    <Student position = "看我一挑五">//开始标签
        <name>瑞萌萌</name>
        <gender>Girl</gender>
        <age>19</age>
        <say>断剑重铸之日,骑士归来之时</say>
    </Student>//结束标签
    <Student position = "我的小熊呢!">//开始标签
        <name> Anne</name>
        <gender>Girl</gender>
        <age>15</age>
        <say>看见我的小熊了么</say>
    </Student>//结束标签
</lanou27>//结束标签

注:带有斜杠的代码 我们定义为结束标签,反之不带则是开始标签
2.解析过程
①SAX(SimpleAPI for XML)
(适合解析大数据 大数据喜欢吃内存 ) NSXMLParser
基于事件回调的形式解析,自己不想做 让别人做就是回调 找代理 ,逐行解析 系统提供的就是这样的
只能读,不能修改,只能顺序访问,适合解析大型XML,解析速度快,实现异构系统的数据访问,实现跨平台
从文档的开始通过每一节点移动,定位一个特定的节点
优点:对内存占有率较低
缺点:效率低 适合大数据
②XML解析步骤:
1、实例化NSXMLParser,传入从服务器接收的XML数据,我们刚在上面定义的 XML 就可以在代码中使用
2、定义解析器代理
常用的代理方法:

1. 开始解析XML文档

- (void)parserDidStartDocument:(NSXMLParser *)parser;

2. 开始解析某个元素,会遍历整个XML,识别元素节点名称,如<Student>开头

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict;

3. 文本节点,得到文本节点里存储的信息数据。 节点中的数据<name>NYX</name>  这里不可以赋值

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;

4. 结束某个节点  如</Student>开头

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName

注意:在解析过程中,2、3、4三个方法会不停的重复执行,直到遍历完成为止

5.解析XML文档结束

- (void)parserDidEndDocument:

3、解析器解析,通过解析代理方法完成XML数据的解析。

下面是代码;

#import "SAXTableViewController.h"
#import "StudentMode.h"
@interface SAXTableViewController ()<NSXMLParserDelegate>//设置代理需要遵守的协议
@property (nonatomic,retain)NSMutableArray *dataSoutse;
@property(nonatomic,retain)StudentMode *stu;
@property (nonatomic,copy)NSString *string;

@end

@implementation SAXTableViewController
//我们用的 MRC  所以要手动释放
- (void)dealloc
{

    [_dataSoutse release];
    [_string release];
    [_stu release];
    [super dealloc];
}
//程序运行会走的方法
- (void)viewDidLoad {
    [super viewDidLoad];
    // 注册 cell  完成我们想要实现的 button 功能
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"reuseIdentifier"];
    [self configureNavigationBar];

}
// 注:网上请求的数据不可以懒加载
#pragma mark -----懒加载-----lazy-loading
-(NSMutableArray *)dataSoutse{
    if (!_dataSoutse) {
        self.dataSoutse =[NSMutableArray arrayWithCapacity:1];
    }return [[_dataSoutse retain]autorelease];
}


//添加 button 属性 完成点击事件
-(void)configureNavigationBar{
    UIBarButtonItem *rightItem =[[UIBarButtonItem alloc]initWithTitle:@"解析" style:(UIBarButtonItemStylePlain) target:self action:@selector(HandlePrase:)];
    self.navigationItem.rightBarButtonItem =rightItem;
    [rightItem release];

}

// 我们的点击事件 通过点击 button 完成将需要的值传入界面中
-(void)HandlePrase:(UIBarButtonItem *)sender{

   //使用系统提供的 NSXMLParser 解析,解析原理:
//    1.读取文件路径
    NSString *filePath =[[NSBundle mainBundle]pathForResource:@"Students" ofType:@"xml"];
//    2.读取数据
    NSData *data =[NSData dataWithContentsOfFile:filePath];
//    3.创建解析对象
    NSXMLParser *parser =[[NSXMLParser alloc]initWithData:data];
//    4.设置代理
    parser.delegate =self;
//    5.开始解析
    [parser parse];
    [parser  release];




}


#pragma mark----解析代理方法的实现------
//开始解析文档会触发的方法
- (void)parserDidStartDocument:(NSXMLParser *)parser{
//    下拉刷新之前需要将上次的东西清空 这样当你刷新的时候就不会重复出现同样的内存 不停的扩充你的indexPath.row;
    self.dataSoutse =nil;
}


//结束解析文档会触发的方法
- (void)parserDidEndDocument:(NSXMLParser *)parser{
//    重新加载数据 刷新作用
    [self.tableView reloadData];
}

//当读取到开始标签的时候触发 比如:<Student> 不带/的
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
    NSLog(@"%@",elementName);
    //设定的 position 里的值是以键值对的形态存在 存放在attributeDict

    if ([elementName isEqualToString:@"Student"]) {
        self.stu =[[StudentMode alloc]init];

        //存储开始节点的属性值
        self.stu.position =attributeDict[@"position"];
     }   

}



//当读取到标签内容后触发的方法,  比如:Nyx  不能在这里赋值
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    self.string =string;
}

//读取到结束标签的时候会触发的方法 ,比如:</Student>
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{

    // 这就是赋值的过程
    if ([elementName isEqualToString:@"name"]) {
        self.stu.name =self.string;
    }else if ([elementName isEqualToString:@"age"]){
        self.stu.age =self.string;
    }else if ([elementName isEqualToString:@"gender"]){
        self.stu.gender =self.string;
    }else if ([elementName isEqualToString:@"say"]){
        self.stu.say =self.string;
    }else if ([elementName isEqualToString:@"Student"]){
        [self.dataSoutse addObject:self.stu];
    }  
}

总结:
SAX解析XML,是基于事件通知的模式,一边读取XML文档一边处理,不必等整个文档加载完之后才采取操作,当在读取解析过程中遇到需要处理的对象,会发出通知对其进行处理。

2.DOM 解析模型就像一个树结构,根节点 ,叶子节点;
GDataXMLNode 是Google 提供的开源的类库,底层有 c 语言实现, < libxml.2.dylib > (动态链接库),C 语言把这个动态链接类库封装成了 OC 中的 XML 解析类,效率比较高;
① GDataXMLNode 使用步骤:
1 taget–Build phases–> link Binary–> 添加一个 libxml2.dylib;
2 taget–>BuildSetting –>Header seacher –>添加了”/usr/include/libxml2”;

libxml2.dylib 相当于一个快捷方式 ,永远都是指向的是 最新的类库, libxml2.2才是真实的类库,当系统类库更新的适合,老版本的 libxml2.dylib 就不需要导入更新后的类库
② DOM 分两种:一种是绝对路径解析 就是只有一条路到达终点;一种是相对路径解析 有多中方法可以达到目的

①布局

#import "DOMTableViewController.h"
#import "StudentMode.h"
#import "GDataXMLNode.h"
@interface DOMTableViewController ()
@property (nonatomic,retain)StudentMode *stu;
@property (nonatomic,retain)NSMutableArray *dataSource;
@end

@implementation DOMTableViewController
- (void)dealloc
{
    [_dataSource release];
    [_stu release];
    [super dealloc];
}
- (void)viewDidLoad {
    [super viewDidLoad];
    //注册 cell 
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
    [self configuerRight];
    [self configuerLeft ];
}

#pragma mark ------lazyLoading------
//重写 setter 方法  懒加载
-(NSMutableArray *)dataSource{

    if (!_dataSource) {
        self.dataSource =[NSMutableArray arrayWithCapacity:1];
    }return [[_dataSource retain] autorelease];

}

//根节点 绝对路径
-(void)configuerLeft{


    UIBarButtonItem *leftItem =[[UIBarButtonItem alloc]initWithTitle:@"RootParser" style:(UIBarButtonItemStylePlain) target:self action:@selector(HandleRootParser:)];
    self.navigationItem.leftBarButtonItem =leftItem;


    [leftItem release];
}
// 相对路径 XPath
-(void)configuerRight{
    UIBarButtonItem *rightItem =[[UIBarButtonItem alloc]initWithTitle:@"XPath" style:(UIBarButtonItemStylePlain) target:self action:@selector(HandleXPath:)];
    self.navigationItem.rightBarButtonItem =rightItem;
    [rightItem release];
}

根节点解析

//通过根节点进行解析
-(void)HandleRootParser:(UIBarButtonItem *)sender{

#warning 清空之前的数据
    self.dataSource = nil;
//    [self.dataSource removeAllObjects]; 也可以达到效果


    //    1.获取文件路径
    NSString *filePath =[[NSBundle mainBundle]pathForResource:@"Students" ofType:@"xml"];

    //    2.根据文件路径初始化 字符串对象
    NSString *xmlStr =[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];

    //3.将解析内容写入 GDataXMLDocment 这个文档 等于存入了内容;
    GDataXMLDocument *docment =[[GDataXMLDocument alloc]initWithXMLString:xmlStr options:0 error:nil];
    //GDataXMLElement (节点对象)

    //    4.获取文档中的节点对象 -->GDataXMLElement;获取根节点
   //    不仅会打印根节点 根节点包括的东西也会打印出来
    GDataXMLElement *rootElement =[docment rootElement];
  //    NSLog(@"%@",rootElement);

    //    5.获取根节点下的所有的 Student 节点
    NSArray *studentArr=[rootElement elementsForName:@"Student"];

    //    6.对数组遍历获取每个学生的节点信息
    for (GDataXMLElement *element in studentArr) {

   //   7.获取 Student 下的叶子节点 就是他的属性
//        name 节点
        GDataXMLElement *nameElement =[[element elementsForName:@"name"] firstObject];

//        age
        GDataXMLElement *ageElement =[[element elementsForName:@"age"] firstObject];

//        gender

        GDataXMLElement *genderElement =[[element elementsForName:@"gender"] firstObject];

//        say
        GDataXMLElement *sayElement =[[element elementsForName:@"say"] firstObject];

//      8  创建学生对象 对其赋值
         StudentMode *stu =[[StudentMode alloc]init];
        stu.name =[nameElement stringValue];
        stu.age =[ageElement stringValue];
        stu.gender =[genderElement stringValue];
        stu.say =[sayElement stringValue];


//9 获取节点中属性值,属性即 GDataXMLNode
        GDataXMLNode *node =[element attributeForName:@"position"];

        stu.position =[node stringValue];

//        10将赋值结束的学生对象 添加到数组 中
        [self.dataSource addObject:stu];
        [stu release];
    }

#warning  解析完之后要刷新
    [self.tableView reloadData];

}

注: 解析完的刷新和 之前的数组清空很重要,反之会出现一样的东西不停的重复

XPath 相对路径解析

#pragma mark------相对路径解析----
-(void)HandleXPath:(UIBarButtonItem *)sender{
    self.dataSource =nil;
    //    1.获取文件路径
    NSString *filePath =[[NSBundle mainBundle]pathForResource:@"Students" ofType:@"xml"];

    //    2.根据文件路径初始化 字符串对象
    NSString *xmlStr =[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];

    //3.将解析内容写入 GDataXMLDocment 这个文档 等于存入了内容;
    GDataXMLDocument *docment =[[GDataXMLDocument alloc]initWithXMLString:xmlStr options:0 error:nil];
    //4. 获取所有的 name 节点  这里是相对路径 只要能找到这个那么就好
#warning 一个/ 是绝对路径 两个// 是相对路径
    NSArray *nameElements= [docment nodesForXPath:@"//name" error:nil];
    NSArray *ageElements =[docment nodesForXPath:@"//age" error:nil];
    NSArray *genderElements =[docment nodesForXPath:@"//gender" error:nil];
    NSArray *sayElements =[docment nodesForXPath:@"//say" error:nil];
//    根节点
    NSArray *stuElements =[docment nodesForXPath:@"//Student" error:nil];
    int  count = (int )nameElements.count;//强制转换
//    5.遍历获取学生信息
    for (int i =0; i <count; i++) {
        GDataXMLElement *nameElement = nameElements[i];
        GDataXMLElement *ageElement =ageElements[i];
        GDataXMLElement *genderElement =genderElements[i];
        GDataXMLElement *sayElement =sayElements[i];
        GDataXMLElement *stuElement =stuElements[i];
//        6.取出节点中的值 为 stu 赋值
        StudentMode *stu =[[StudentMode alloc]init];
        stu.name = [nameElement stringValue];
        stu.age =[ageElement stringValue];
        stu.gender =[genderElement stringValue];
        stu.say =[sayElement stringValue];

        //获取节点中属性值,属性 GDataXMLNode
       GDataXMLNode *node=[stuElement attributeForName:@"position"];
//        为属性赋值
        stu.position =[node stringValue];
//       6 添加到数组中
        [self.dataSource addObject:stu];

        [stu release];



    }
    [self.tableView reloadData];


}

总结:
1.根节点和 XPath 都是通过遍历 赋值 来找到你想要的数据
2.别忘了 在设定 section 和 row 的方法中开辟空间
3.重用 cell 方法

三 JSON 非常便利的解析方法 他的数据源和 XML 也不一样

[
 {
 "name":"Nyx",
 "gender":"Girl",
 "age":15,
 "say":"你是看不起我么"

 },

 {
 "name":"暴风女神",
 "gender":"Girl",
 "age":"17",
 "say":"风之化身听你差遣"
 },

 {
 "name":"堕落天使 莫甘娜",
 "gender":"Gilr",
 "age":"18",
 "say":"他们将会痛苦不堪"
 },

 {
 "name":"狂野女猎手 奶大力",
 "gender":"Girl",
 "age":"17",
 "say":"狂野 将使他们感到畏惧"
 },

 {
 "name":"迅捷斥候 提莫",
 "gender":" Boy",
 "age":"16",
 "say":"我去前面探探路"
 }
 ]

最外层是数组 里面每一组数据是字典

2.解析代码
①系统解析


#import "JSONTableViewController.h"
#import "StudentMode.h"
#import "JSONKit.h"
@interface JSONTableViewController ()
@property (nonatomic,retain)NSMutableArray *dataSource;
@end

@implementation JSONTableViewController
- (void)dealloc
{
    [_dataSource release];
    [super dealloc];
}



//懒加载 重写 setter 方法
-(NSMutableArray *)dataSource{
    if (!_dataSource) {
        self.dataSource = [NSMutableArray arrayWithCapacity:0];
    }return [[_dataSource retain] autorelease];
}





- (void)viewDidLoad {
    [super viewDidLoad];
    [self configuerRight];
    [self configuerLeft ];
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];

    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
#pragma mark------系统的解析
-(void)configuerLeft{


    UIBarButtonItem *leftItem =[[UIBarButtonItem alloc]initWithTitle:@"系统" style:(UIBarButtonItemStylePlain) target:self action:@selector(HandleSystem:)];
    self.navigationItem.leftBarButtonItem =leftItem;


    [leftItem release];
}


-(void)HandleSystem:(UIBarButtonItem *)sender{
    self.dataSource = nil;
//    1.获取文件路径
    NSString *filePath =[[NSBundle mainBundle]pathForResource:@"Student"ofType:@"json"];

//    2.根据文件路径  初始化 NSData 对象
    NSData *data= [NSData dataWithContentsOfFile:filePath];

//    3.解析了
    NSMutableArray *arr =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
    self.dataSource =[NSMutableArray arrayWithCapacity:1];
    for (NSDictionary *dic in arr) {
        StudentMode *stu =[[StudentMode alloc]init];
        [stu setValuesForKeysWithDictionary:dic];
        [self.dataSource addObject:stu];
        [stu release];
    }

    [self.tableView reloadData];
}

② 第三方解析 需要引入你的第三方 我在这里用的是 JSONKit

#pragma mark-----第三方解析--------

-(void)configuerRight{
    UIBarButtonItem *rightItem =[[UIBarButtonItem alloc]initWithTitle:@"第三方" style:(UIBarButtonItemStylePlain) target:self action:@selector(HandThirdPrase:)];
    self.navigationItem.rightBarButtonItem =rightItem;
    [rightItem release];
}


-(void)HandThirdPrase:(UIBarButtonItem *)sender{
    self.dataSource = nil;
    //JSONKit通过对NSString,NSData添加分类的形式,添加解析的功能

    //JSONKit 通过对NSString ,NSData添加分类的形式,添加了一个解析的功能
        //1,获取文件路径
        NSString *filePath = [[NSBundle mainBundle ]pathForResource:@"Student" ofType:@"json"];
        //2,根据文件路径初始化字符串对象
        NSString *dataStr = [NSString stringWithContentsOfFile:filePath encoding:(NSUTF8StringEncoding) error:nil];
        //3,解析OC对象,(返回值可以选择可变或不可变)
        //dataStr 调用分类的方法
            NSArray *arr1 = [dataStr objectFromJSONString];
//            NSLog(@"%@",arr1);
            NSMutableArray *arr2 = [dataStr mutableObjectFromJSONString];
//            NSLog(@"%@",arr2);


        //根据文件路径初始化NSData 对象
       NSData *data = [NSData dataWithContentsOfFile:filePath];
//       NSLog(@"%@",data);
//        解析 (可变/不可变)  取不到数据????
        NSArray *arr3 = [data objectFromJSONData];
//        NSLog(@"%@",arr3);
        NSMutableArray *arr4 = [data mutableObjectFromJSONData];
//        NSLog(@"%@",arr4);
    self.dataSource =[NSMutableArray arrayWithCapacity:1];
    for (NSDictionary *dic in arr4) {
        StudentMode *stu =[[StudentMode alloc]init];
        [stu setValuesForKeysWithDictionary:dic];
        [self.dataSource addObject:stu];
        [stu release];
    }
    [self.tableView reloadData];

    }

总结:
1.所有的解析数据 步骤大致:
①获取文件地址
②根据文件初始化你所订的对象类型
③存入数据
④遍历
⑤赋值
2. 方法的清空和刷新 是每一个解析方法必备!
3. XML 的方法 需要多练习掌握

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值