iOS数据解析UI_14

简介: 数据解析:就是按照约定(假象)好的格式提取数据的过程就叫解析;  提供数据方(后台):工作就是把数据按照一定的格式存储起来  提取数据方(前台):工作就是把数据按照一定的格式读取出来  主流的格式:XML格式  /   JSON格式  ,此两种格式无论前台还是后台都必须熟悉    ...
数据解析:就是按照约定(假象)好的格式提取数据的过程就叫解析;
 提供数据方(后台):工作就是把数据按照一定的格式存储起来
 提取数据方(前台):工作就是把数据按照一定的格式读取出来
 主流的格式:XML格式  /   JSON格式  ,此两种格式无论前台还是后台都必须熟悉
 
 XML以标签的形式存在,标签由开始标签和结束标签,这一对标签就做节点;
 没有父节点的节点叫做根节点,没有子节点的节点就做叶子节点,而我们要使用的数据都在叶子节点中存储;

 XML解析的两种工作原理:
 1.SAX   基于事件回调(找代理)的解析方法方式,逐行解析,效率低,适合大数据解析,是系统提供的;
 2.DOM   把要解析的数据全部读取到内存中,把数据初始化成树状结构,逐层解析,效率高,只适合小数据解析,谷歌提供的第三方解析方法;
—————————————————第一部分SAX解析———————————————————
素材下载Students.xml: http://pan.baidu.com/s/1hqji1IO
JiSON解析素材下载: http://pan.baidu.com/s/1mgnefsW
页面基本的搭建不做介绍!
公用model数据模型:
Student.h
@interface Student : NSObject
@property(nonatomic,copy)NSString *name;//姓名
@property(nonatomic,copy)NSString *gender;//性别
@property(nonatomic,copy)NSString *age;//年龄
@property(nonatomic,copy)NSString *says;//座右铭
@property(nonatomic,retain)NSString *position;//属性
@end
Student.m
@implementation Student
-(void)dealloc{
    self.name = nil;
    self.gender = nil;
    self.says = nil;
    self.age = nil;
    self.position = nil;
    [super dealloc];
}
//防止未找到key值所对的value造成Crash
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{

}
@end
—————————————————
两个方法的cell显示一样UITableViewCell

SAXViewController.m

#import "SAXViewController.h"
#import "Student.h"
@interface SAXViewController ()<NSXMLParserDelegate>
//存储从xml中解析出来的学生对象
@property(nonatomic,retain)NSMutableArray *dataSource;
@property(nonatomic,retain)Student *student;//存储使用学生对象读取到的信息
@property(nonatomic,retain)NSMutableString *string;//存储读取到节点中的数据
@end

@implementation SAXViewController
- (void)dealloc{
    self.dataSource = nil;
    self.student = nil;
    self.string = nil;
    [super dealloc];
}

- (IBAction)handleParser:(UIBarButtonItem *)sender {

//NSXMLParser  系统提供的解析xml文件的类
    //第一步:获取文件路径
    NSString *filePath = [[NSBundle mainBundle]pathForResource:@"Students.xml" ofType:nil];

    //第二步:创建解析对象
    //创建一个NSData对象
    NSData *data = [NSData dataWithContentsOfFile:filePath];
    NSXMLParser *parser =[[NSXMLParser alloc]initWithData:data];
    //制定代理
    parser.delegate = self;
    //开始解析
    [parser parse];
    //释放
    [parser release];

}
- (NSMutableArray *)dataSource{
    if (_dataSource == nil) {
        self.dataSource = [NSMutableArray arrayWithCapacity:0];
    }
    return [[_dataSource retain]autorelease];
}

#pragma mark xmlPoarserDelegate 代理方法
//开始解析的时候触发这个方法
- (void)parserDidStartDocument:(NSXMLParser *)parser{
//    NSLog(@"开始解析了");
    //开始解析的时候清空数组中的内容
    [self.dataSource removeAllObjects];

}

//读到开始标签的时候开始触发
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{

    //当读取到Student开始标签的时候创建学生对象
    if ([elementName isEqualToString:@"Student"]) {
        self.student = [[Student alloc]init];
        self.student.position = attributeDict[@"position"];

    }
    //读取到开始标签就初始化字符串self.string
    self.string = [NSMutableString stringWithCapacity:0];

}

//读到结束标签的时候开始触发
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{

    if ([elementName isEqualToString:@"name"]) {
        self.student.name = self.string;
    }else if([elementName isEqualToString:@"age"]){
        self.student.age = self.string;
    }else if([elementName isEqualToString:@"gender"]){
        self.student.gender = self.string;
    }else if ([elementName isEqualToString:@"says"]){
        self.student.says = self.string;
    }else if ([elementName isEqualToString:@"Student"]){
        //把学生对象添加到数组中
        [self.dataSource addObject:self.student];

        [self.student release];

    }

}

//当读到开始标签后的数据触发
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    //string 存储的就是读到的数据

    //由于系统的解析能力是有限的,如果节点中的内容过长,不能一次性全部读取,此时要把,每次读取到的内容拼接在一起
    [self.string appendString:string];

}

//结束解析的时候触发
- (void)parserDidEndDocument:(NSXMLParser *)parser{
//    NSLog(@"解析结束了");
//在这里让tableView重新刷新一下ui,重新走一遍数据源方法
    [self.tableView reloadData];

}
//返回分区个数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
//返回行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.dataSource.count;
}
//显示
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"sax" forIndexPath:indexPath];

    //根据cell的下标取出对应的学生
    Student *s = self.dataSource[indexPath.row];
    cell.textLabel.text = s.name;
    return cell;
}
最终效果:

——————————————————————————————————————————————————

————————————————第二部分Dom解析———————————————
两个方法的cell显示一样UITableViewCell

2.  GDataXMLNode 是由Google提供的开源的基于C语言的libxml2.dylib动态链接类库封装的OC xml解析类,效率比较高
 使用GDataXMLNode 步骤:
 1.target -->Build Phases--link Binary 添加libxml2.dylib
 2.target -->Build setting   搜 header seach Path 双击后缀添加 /usr/include/libxml2
 libxml2.dylib 和 libxml2.2dylib 的区别:前一个是快捷方式,永远指向最新的实体类库,而后一个才是真正的实体类库,使用前一个好处,当系统实体类库更新的时候,老版本的项目就无需再重新导入实体类库;
DOMViewController.m

#import "DOMViewController.h"
#import "GDataXMLNode.h"
#import "Student.h"
@interface DOMViewController ()
@property(nonatomic,retain)NSMutableArray *dataSource;
@end

@implementation DOMViewController
- (void)dealloc{
    self.dataSource = nil;
    [super dealloc];
}
//懒加载创建数组
- (NSMutableArray *)dataSource{
    if (_dataSource == nil) {
        self.dataSource = [NSMutableArray arrayWithCapacity:0];
    }
    return [[_dataSource retain]autorelease];
}
                            ==============RootParser解析=================

- (IBAction)handleRootParser:(UIBarButtonItem *)sender {
    //解析开始之前把数组中的元素清空
    self.dataSource = nil;

    //拿到文件的路径
    NSString *filePath = [[NSBundle mainBundle]pathForResource:@"Students.xml" ofType:nil];

    //将文件内容存储到字符串中
    NSString *xmlStr = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];

    //将要解析的内容写入到GDataXMLDocument 类中
    //第二个参数是一个预留参数,就是这个方法的作者,在写这个方法时预留一个参数的位置,留待以后对方的扩充
    GDataXMLDocument *document = [[GDataXMLDocument alloc]initWithXMLString:xmlStr options:0 error:nil];
    // GDataXMLElement   节点类
    // GDataXMLNode  属性类
    //获取document 中所有的根节点
    GDataXMLElement *rootElement = [document rootElement];
//    NSLog(@"%@",rootElement);//验证
    //获取根节点下的所有Student节点
   NSArray *stuElements =  [rootElement elementsForName:@"Student"];
//        NSLog(@"%@",stuElement);//验证

    //遍历数组,获取每一个Student节点
    for (GDataXMLElement *stuElement in stuElements) {
        //获取Student节点下的name/age/gender/says    因为只有一个元素所有firstObject和lastObject一样
        GDataXMLElement *nameElement = [[stuElement elementsForName:@"name"]lastObject];
        GDataXMLElement *ageElement = [[stuElement elementsForName:@"age"]lastObject];
        GDataXMLElement *genderElement = [[stuElement elementsForName:@"gender"]firstObject];
        GDataXMLElement *saysElement = [[stuElement elementsForName:@"says"]firstObject];
        /*//打印每个节点对象中的数据     验证!
        NSLog(@"%@",[nameElement stringValue]);
        NSLog(@"%@",[ageElement stringValue]);
        NSLog(@"%@",[genderElement stringValue]);
        NSLog(@"%@",[saysElement stringValue]);
        NSLog(@"________________________");
        */
        //创建学生对象,存储节点对象中的数据
        Student *stu = [[Student alloc]init];
        stu.name = [nameElement stringValue];
        stu.age = [ageElement stringValue];
        stu.gender = [genderElement stringValue];
        stu.says = [saysElement stringValue];

        //取出学生节点对象中的属性
        GDataXMLNode *node = [stuElement attributeForName:@"position"];
        stu.position = [node stringValue];

        //将学生对象添加到数组织中
        [self.dataSource addObject:stu];
        [stu release];
}
    [self.tableView reloadData];

//    NSLog(@"%@",self.dataSource); //验证
    //释放xml文本对象
    [document release];
}

RootParser解析效果:

————————————————————————————————————————————

                         ==============xPath相对路径解析=================

- (IBAction)handleXPath:(UIBarButtonItem *)sender {

    //清空数组
    [self.dataSource removeAllObjects];

    //拿到文件的路径
    NSString *filePath = [[NSBundle mainBundle]pathForResource:@"Students.xml" ofType:nil];

    //将文件内容存储到字符串中
    NSString *xmlStr = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];


    //将要解析的内容写入到GDataXMLDocument 类中
    //第二个参数是一个预留参数,就是这个方法的作者,在写这个方法时预留一个参数的位置,留待以后对方的扩充
    GDataXMLDocument *document = [[GDataXMLDocument alloc]initWithXMLString:xmlStr options:0 error:nil];

    //通过相对路径获取name,age,gender,says 节点
    //姓名节点
      NSArray *nameElements = [document nodesForXPath:@"//name" error:nil];
    //年龄节点
    NSArray *ageElements = [document nodesForXPath:@"//age" error:nil];
    //性别节点
    NSArray *genderElements = [document nodesForXPath:@"//gender" error:nil];
    //座右铭节点
    NSArray *saysElements = [document nodesForXPath:@"//says" error:nil];
    //学生节点
    NSArray *studentElements = [document nodesForXPath:@"//Student" error:nil];
    //求出学生节点数组中元素的个数
  int count = (int)studentElements.count;
    for (int i = 0; i < count; i ++) {
        //创建节点对象接收数组中对应位置的元素
        GDataXMLElement *nameElement = nameElements[i];
        //取出年龄节点
        GDataXMLElement *ageElement = ageElements[i];
        //取出性别节点
        GDataXMLElement *genderElement = genderElements[i];
        //取出says节点
        GDataXMLElement *saysElement = saysElements[i];
        //取出学生节点
        GDataXMLElement *studentElement = studentElements[i];
        //创建学生对象存储节点中的内容
        Student *s = [[Student alloc]init];
        s.name = [nameElement stringValue];
        s.age = [ageElement stringValue];
        s.gender = [genderElement stringValue];
        s.says = [saysElement stringValue];

        //取出学生节点中的属性
        GDataXMLNode *node = [studentElement attributeForName:@"position"];
        s.position = [node stringValue];
        //添加到数组中
        [self.dataSource addObject:s];
         //释放
        [s release];
    }

    //刷新UI界面
    [self.tableView reloadData];
    [document release];
}
//返回分区
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.dataSource.count;
}
//显示
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"dom" forIndexPath:indexPath];
//取值给model类Student对象
    Student *s = self.dataSource[indexPath.row];
//赋值
    cell.textLabel.text = s.position;

    return cell;
}
xPath相对路径解析效果:


——————————————————————————————————————————————
=======================第三部分JiSON=========================
两个方法的cell显示一样UITableViewCell


JSONViewController.m

#import "JSONViewController.h"
#import "Student.h"
#import "JSONKit.h"
@interface JSONViewController ()
@property(nonatomic,retain)NSMutableArray *dataSource;

@end

@implementation JSONViewController
- (void)dealloc{
    self.dataSource = nil;
    [super dealloc];
}

//懒加载
- (NSMutableArray *)dataSource{
    if (_dataSource == nil) {
        self.dataSource = [NSMutableArray arrayWithCapacity:0];
    }
    return [[_dataSource retain]autorelease];
}
                            ==============系统方法解析=================

- (IBAction)handleSystomParser:(UIBarButtonItem *)sender {

    //清空字典内容
    self.dataSource = nil;
    //1.获取文件路径
    NSString *filePath = [[NSBundle mainBundle]pathForResource:@"Student.json" ofType:nil];

    //2.将JSON文件读取到Data对象中
    NSData *date = [NSData dataWithContentsOfFile:filePath];
    //    NSJSONReadingMutableContainers = (1UL << 0),   返回容器是可变容器
    //    NSJSONReadingMutableLeaves = (1UL << 1),  返回的找到的数据的是可变的数据

    //json的最外层是数组,所以用数组接收
  NSMutableArray *dataSource = [NSJSONSerialization JSONObjectWithData:date options:(NSJSONReadingMutableContainers) error:nil];

    //数组中都是字典,所以遍历字典
    for (NSDictionary *dic in dataSource) {
        //创建一个学生对象
        Student *stu = [[Student alloc]init];
        //kvc赋值
        [stu setValuesForKeysWithDictionary:dic];
        //加到数组里
        [self.dataSource addObject:stu];

        //释放
        [stu release];

    }

    //刷新ui
    [self.tableView reloadData];

}
系统方法解析效果:


——————————————————————————————————
                           ==============第三方解析=================

- (IBAction)handleThridParer:(UIBarButtonItem *)sender {

    //清除数组
    self.dataSource = nil;
    //获取文件路径
    NSString *filePath = [[NSBundle mainBundle]pathForResource:@"Student.json" ofType:nil];
/*系统方法暂时不用(注掉)
    NSString *jsonStr = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    //1.通过json格式的字符串解析json数据    objectFromJSONString返回的数据可以使用可变容器接收也可以使用不可变容器接收
      NSArray *dataArray =   [jsonStr objectFromJSONString];
      NSLog(@"%@",dataArray);
    */
    新方法
    //2.通过NSDate对象完成解析   objectFromJSONData返回的数据可以使用可变容器接收也可以使用不可变容器接收
    NSData *data = [NSData dataWithContentsOfFile:filePath];
    NSArray *dataArray2 = [data objectFromJSONData];
//    NSLog(@"%@",dataArray2); 验证!
        //数组中都是字典,所以遍历字典
    for (NSDictionary *dic in dataArray2) {
        //创建
        Student *stu = [[Student alloc]init];
        [stu setValuesForKeysWithDictionary:dic];
        [self.dataSource addObject:stu];
        [stu release];

    }
    [self.tableView reloadData];

}
//返回分区
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1;
}
//返回行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.dataSource.count;
}
//显示
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"json" forIndexPath:indexPath];
    //取值
    Student *s = self.dataSource[indexPath.row];
    //显示
    cell.textLabel.text = s.says;
    return cell;
}
第三方解析效果:



目录
相关文章
|
10月前
|
Linux Go iOS开发
IDA 9.2 发布:Golang 改进、新 UI 组件、类型解析等
IDA Pro 9.2 (macOS, Linux, Windows) - 强大的反汇编程序、反编译器和多功能调试器
1573 0
|
12月前
|
人工智能 JSON 前端开发
如何解决后端Agent和前端UI之间的交互问题?——解析AG-UI协议的神奇作用
三桥君指出AG-UI协议通过SSE技术实现智能体与前端UI的标准化交互,解决流式传输、实时进度显示、数据同步等开发痛点。其核心功能包括结构化事件流、多Agent任务交接和用户中断处理,具有"一次开发到处兼容"、"UI灵活可扩展"等优势。智能体专家三桥君认为协议将AI应用从聊天工具升级为实用软件,适用于代码生成、多步骤工作流等场景,显著提升开发效率和用户体验。
2690 0
|
自然语言处理 安全 JavaScript
HarmonyOsNEXT【ArkUI超全解析】新手必看的方舟UI框架指南!
本文是HarmonyOS NEXT方舟UI框架新手指南,涵盖ArkTS开发核心知识点。从UI与组件基础概念到声明式开发优势,再到ArkTS代码实战,包括组件创建、属性设置、事件绑定等。通过实例解析自定义组件开发流程,提供避坑技巧与代码风格建议,助你快速掌握ArkUI框架精髓,轻松构建高效、美观的HarmonyOS应用界面。适合初学者及希望转型声明式开发的开发者学习参考。
|
数据采集 JSON 数据可视化
JSON数据解析实战:从嵌套结构到结构化表格
在信息爆炸的时代,从杂乱数据中提取精准知识图谱是数据侦探的挑战。本文以Google Scholar为例,解析嵌套JSON数据,提取文献信息并转换为结构化表格,通过Graphviz制作技术关系图谱,揭示文献间的隐秘联系。代码涵盖代理IP、请求头设置、JSON解析及可视化,提供完整实战案例。
883 4
JSON数据解析实战:从嵌套结构到结构化表格
|
JavaScript 测试技术 Python
UI自动化测试中的元素等待机制解析
在UI自动化测试中,元素定位失败常因页面存在iframe或缺乏合理等待机制。本文解析三种等待策略及其应用场景:显式等待可精确控制单个元素等待条件,支持自定义轮询;隐式等待全局生效,适合简单页面加载;强制等待仅用于临时调试,正式脚本慎用。通过对比三者执行精度、资源消耗及适用场景,帮助选择最优策略,提升测试效率与稳定性。
|
JSON 监控 网络协议
Bilibili直播信息流:连接方法与数据解析
本文详细介绍了自行实现B站直播WebSocket连接的完整流程。解析了基于WebSocket的应用层协议结构,涵盖认证包构建、心跳机制维护及数据包解析步骤,为开发者定制直播数据监控提供了完整技术方案。
2454 9
|
机器学习/深度学习 JSON 算法
淘宝拍立淘按图搜索API接口系列的应用与数据解析
淘宝拍立淘按图搜索API接口是阿里巴巴旗下淘宝平台提供的一项基于图像识别技术的创新服务。以下是对该接口系列的应用与数据解析的详细分析
|
Java API 数据处理
深潜数据海洋:Java文件读写全面解析与实战指南
通过本文的详细解析与实战示例,您可以系统地掌握Java中各种文件读写操作,从基本的读写到高效的NIO操作,再到文件复制、移动和删除。希望这些内容能够帮助您在实际项目中处理文件数据,提高开发效率和代码质量。
984 4
|
缓存 监控 搜索推荐
【实战解析】smallredbook.item_get_video API:小红书视频数据获取与电商应用指南
本文介绍小红书官方API——`smallredbook.item_get_video`的功能与使用方法。该接口可获取笔记视频详情,包括无水印直链、封面图、时长、文本描述、标签及互动数据等,并支持电商场景分析。调用需提供`key`、`secret`和`num_iid`参数,返回字段涵盖视频链接、标题、标签及用户信息等。同时,文章提供了电商实战技巧,如竞品监控与个性化推荐,并列出合规注意事项及替代方案对比。最后解答了常见问题,如笔记ID获取与视频链接时效性等。
|
存储 缓存 监控
如何高效爬取天猫商品数据?官方API与非官方接口全解析
本文介绍两种天猫商品数据爬取方案:官方API和非官方接口。官方API合法合规,适合企业长期使用,需申请企业资质;非官方接口适合快速验证需求,但需应对反爬机制。详细内容涵盖开发步骤、Python实现示例、反爬策略、数据解析与存储、注意事项及扩展应用场景。推荐工具链包括Playwright、aiohttp、lxml等。如需进一步帮助,请联系作者。

热门文章

最新文章

推荐镜像

更多
  • DNS