UI day 14 XML JSON数据结构解析

本文详细介绍了XML和JSON数据结构的解析方法,包括SAX、DOM解析原理及使用GDataXMLNode类进行DOM解析的步骤,并展示了如何将解析后的数据应用于iOS应用中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                       XML数据结构
1.解析:就是按照约定好(假象)的格式提取数据的过程解析
提供数据方(后台):工作就是把数据按照一定的格式存储起来
提取数据方(前台):工作就是把数据按照一定得格式读取出来
主流的格式:XML格式    JSON格式  此两种格式无论前台还是后台都必须熟悉

2.XML的数据以标签的形式存在,标签有开始标签和结束标签,管这一对标签叫做节点
没有父节点的节点叫做根节点,没有子节点的节点叫做叶子节点,而我们使用的数据都存在叶子节点中存储

3.XML解析的两种工作原理
(1)SAX  基于事件回调(找代理)的解析方式,逐行解析,效率低,适合大数据解析,是系统提供的
(2)DOM 把要解析的数据一下子全部读取到内存中,把数据初始化成树状结构,逐层进行解析,效率高,只适合小数据解析(谷歌提供的第三方解析方式)

                SAX解析      利用storyboard布局   在建一个Model类

(1)@interface SAXViewController ()<NSXMLParserDelegate>
//存储从xml文件中解析出来的学生对象
@property (nonatomic,retain)NSMutableArray *dataSource;
@property (nonatomic,retain)Student *student;//使用学生对象存储读取到的信息
@property (nonatomic,retain)NSMutableString *string;//存储读取到节点中的数据
@end
@implementation SAXViewController
(2)- (void)dealloc
{
    self.dataSource = nil;
    self.student = nil;
    self.string = nil;
    [super dealloc];
}
(3)懒加载
- (NSMutableArray *)dataSource
{
    if (_dataSource == nil) {
        self.dataSource = [NSMutableArray arrayWithArray:0];
    }
    return [[_dataSource retain]autorelease];
}
(4) - (IBAction)handleParser:(UIBarButtonItem *)sender {
//    NSLog(@"解析");
//    系统提供的解析XML文件的类NSXMLParser
//    1.获取文件路径
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Students.xml" ofType:nil];
//    2.创建NSData对象
    NSDatT a *data = [NSData dataWithContentsOfFile:filePath];
    //3.创建解析对象
    NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];
//    4.指定代理
    parser.delegate = self;
//    5.开始解析
    [parser parse];
//    6.释放
    [parser release];
}

(5) #pragma mark XMLparser的代理方法
//开始解析的时候触发这个方法
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
//    NSLog(@"开始解析了");
//   开始解析的时候清空数值中的内容
    [self.dataSource removeAllObjects];
}
//读取到开始标签的时候触发
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
//    NSLog( @"%@",attributeDict);
//    NSLog(@"%@",elementName);
//    当读取到student开始标签的时候创建学生对象
    if ([elementName isEqualToString:@"student"]) {
        self.student = [[Student alloc]init];
       
        self.student.position = attributeDict[@"position"];
     
    }
//    #####21读取到开始标签就初始化字符串self.string
    self.string = [NSMutableString stringWithCapacity:0];
}
//当读取到开始标签后的数据时触发
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string//string就是存储的读取得到的数据
{
//    NSLog(@"%@",string);
    //使用属性保存节点中间的数据
//    #####21由于系统的解析能力是有限的如果节点中的内容过长不能够一次性全部读取,此时,要把每次读取的内容拼接到一起
    [self.string appendString:string];
}

//读取到结束标签的时候触发
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
//     NSLog(@"==%@",elementName);
    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)parserDidEndDocument:(NSXMLParser *)parser
{
  
//    NSLog(@"%@",self.dataSource);
//     NSLog(@"解析结束了");
//    在这里让tableView重新刷新一次UI,重新走一遍数据源代理方法
    [self.tableView reloadData];
   
}

(6) - (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];
    Student *s = self.dataSource[indexPath.row];//根据cell的下标取出对应的学生
    cell.textLabel.text = s.name;
    return cell;
}
@end
                                DOM解析    利用storyboard布局

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

(1)
@interfaceDOMViewController ()
@property (nonatomic,retain)NSMutableArray *dataSource;
@end
(2)
@implementation DOMViewController
- (void)dealloc
{
    self.dataSource = nil;
    [super dealloc];
}

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

(4) - (IBAction)handleRootParser:(UIBarButtonItem *)sender {
//    解析开始之前把数组中的元素清空
    self.dataSource = nil;
   
//    1.读取文件的路径
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Students.xml" ofType:nil];
//    2.将文件内容存储到字符串中
    NSString *xmlStr = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
//    3.将要解析的内容写入到GDataxmlDocument内容
//    / 第二个参数是一个预留参数,就是这个方法的作者,在写着方法时预留一个参数的位置,留待以后对方的扩充
    GDataXMLDocument *document = [[GDataXMLDocument alloc]initWithXMLString:xmlStr options:0 error:nil];
//    GDataXMLElement节点类
//    GDataXMLNode 它里面存的是属性对象  是个属性类
//   4. 获取document中所有的根节点
    GDataXMLElement *rootElement = [document rootElement];
//    NSLog(@"%@",rootElement);
//   5. 获取根节点下的所有student节点
 NSArray  *stuElements = [rootElement elementsForName:@"student"];
//    NSLog(@"%@",stuElements);
//   6. 遍历数组,获取每一个student节点
    for (GDataXMLElement *stuElement in stuElements) {
//   7. 获取student节点下的name/age/gnder/says节点
        GDataXMLElement *nameElement = [[stuElement  elementsForName:@"name"]lastObject];
        GDataXMLElement *ageElement = [[stuElement elementsForName:@"age"]lastObject];
        GDataXMLElement *genderElement = [[stuElement elementsForName:@"gender"]lastObject];
        GDataXMLElement *saysElement = [[stuElement elementsForName:@"says"]lastObject];
        /*
//      打印每个节点对象中的数据 stringvalue方法可以返回节点对象中的数据
        NSLog(@"%@",[nameElement stringValue]);
        NSLog(@"%@",[ageElement stringValue]);
        NSLog(@"%@",[genderElement stringValue]);
        NSLog(@"%@",[saysElement stringValue]);
        NSLog(@"==================================");
        */
//   8.创建学生对象,存储节点对象中的数据
        Student *stu = [[Student alloc]init];
        stu.name = [nameElement stringValue];
        stu.age = [ageElement stringValue];
        stu.gender = [genderElement stringValue];
        stu.says = [saysElement stringValue];
//   10. 取出学生节点对象中的属性
        GDataXMLNode *node = [stuElement attributeForName:@"position"];
        stu.position = [node stringValue];
//   9.  将学生对象添加到数组中
        [self.dataSource addObject:stu];

        [stu release];
     
    }
    [self.tableView reloadData];//更新UI
    NSLog(@"%@",self.dataSource);
//    释放掉xml文本对象
    [document release];
}

(5) - (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];
    Student *s = self.dataSource[indexPath.row];
    cell.textLabel.text = s.position;
  
    return cell;
}
@end

                                             JSON数据结构解析
(1)
#import "JSONViewController.h"
#import "Student.h"
#import "JSONKit.h"
@interface JSONViewController ()
@property (nonatomic,retain)NSMutableArray *dataSource;
@end
(2) @implementation JSONViewController
- (void)dealloc
{
    self.dataSource = nil;
    [super dealloc];
}
(3)懒加载
- (NSMutableArray *)dataSource
{
    if (_dataSource == nil) {
        self.dataSource = [NSMutableArray arrayWithCapacity:0];
    }
    return [[_dataSource retain]autorelease];
}

(4) - (IBAction)handleSystem:(UIBarButtonItem *)sender {
    self.dataSource = nil;
    NSLog(@"系统");
//    1.获取文件路径
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Student.json" ofType:nil];
//    2.json文件读取到NSDate对象中
    NSData *data = [NSData dataWithContentsOfFile:filePath];
//    NSJSONReadingMutableContainers返回的容器是可变的容器
//    NSJSONReadingMutableLeaves返回的找到的数据时可不的数据
//    3.json文件的最外层是数组,所有用数组接收
  NSMutableArray  *dataSource = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
   
//    NSLog(@"%@",dataSource);
//   3. 数组中都是字典对象,所以遍历字典
    for (NSDictionary *dic in dataSource) {
        Student *stu = [[Student alloc]init];
        [stu setValuesForKeysWithDictionary:dic];
        [self.dataSource addObject:stu];
        [stu release];
   
    }
   
//    刷新UI
    [self.tableView reloadData];

}

(5) - (IBAction)handleThird:(UIBarButtonItem *)sender {
    self.dataSource = nil;
//    NSLog(@"第三方");
//    1.获取文件路径
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Student.json" ofType:nil];

{
    NSString *jsonStr = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
// 2. 第一种解析  通过JSON格式字符串解析JSON数据 objectFromJSONString返回的数据可以使用可变容器接收也可以使用不可变容器接收
   NSArray *dataArray =[jsonStr objectFromJSONString];
//    NSLog(@"%@",dataArray);
 }
  
//  2. 第二种解析 通过NSData对象完成解析
    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];
   
}

(6) - (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 *stu = self.dataSource[indexPath.row];
   
    cell.textLabel.text = stu.age;

    return cell;
}
@end
































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值