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

来源:互联网 发布:魔神英雄传 知乎 编辑:程序博客网 时间:2024/06/09 21:57

一 什么是解析?
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
原创粉丝点击