iOS进阶_XML(XML解析思路与代码实现)

XML曾经是最流行的,出身名门 W3C主推 IBM & 微软

XML -> 可拓展“标记”语言

<标记></标记>  <标记>标记的内容</标记>

<标记 属性1=“值”,属性2=“值”>标记的内容</标记>

解析方式:

  • DOM节点解析方式 MAC提供的解析方式,iOS无法直接使用
    -原因:内存开销巨大
    -将数据以树形结构加载到内容

  • SAX iOS提供的解析方式

    • 内存开销小
    • 速度快
    • 只读
    • 从上到下,顺序解析过程

    ———–SAX解析的过程———-
    1.打开文档(准备)
    2.开始节点

<videos>
            <video videoId="1">
                <name>
                <length>

3.发现节点内容(一个节点内容,可能会读取很多次!)
01.C
语言-
语法预览
320
….
4.结束节点

</name>
            </length>
            ....
        </video>
   </videos>     (最后一个节点)
判断文档是否解析结束,如果没有就继续

5.文档解析完成!

在实际开发中,XML的解析是用过NSXMLParser的对象来实现!具体的实现过程,是通过”五个代理”方法不断循环,来完成XML解析!

XML解析思路与代码实现

这里写图片描述

Video.h 创建Video模型

#import <Foundation/Foundation.h>

@interface Video : NSObject

/* id */
@property(strong,nonatomic)NSNumber * videoId;
@property(copy,nonatomic)NSString * name;
@property(strong,nonatomic)NSNumber * length;
@property(copy,nonatomic)NSString * videoURL;
@property(copy,nonatomic)NSString * imageURL;
@property(copy,nonatomic)NSString * desc;
@property(copy,nonatomic)NSString * teacher;

@property(nonatomic,readonly)NSString * time;

-(instancetype)initWithDict:(NSDictionary *)dict;
+(instancetype)videoWithDict:(NSDictionary *)dict;

@end

Video.m文件

#import "Video.h"

@implementation Video

-(NSString *)time{
    int len = self.length.intValue;

    //时分秒
    return [NSString stringWithFormat:@"%02d:%02d:%02d",len/3600,(len % 3600)/60,(len % 60)];
}

-(instancetype)initWithDict:(NSDictionary *)dict{
    self = [super init];
    if(self){
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

+(instancetype)videoWithDict:(NSDictionary *)dict{

    return [[self alloc]initWithDict:dict];
}

//重写description方法
-(NSString *)description{
    return [NSString stringWithFormat:@"<%@:%p>{videoId :%@,name : %@,length : %@ ,videoURL : %@,imageURL : %@,desc : %@,teacher : %@}",[self class],self,self.videoId,self.name,self.length,self.videoURL,self.imageURL,self.desc,self.teacher];
}
@end
#import "ViewController.h"
#import "Video.h"

@interface ViewController ()<NSXMLParserDelegate>
//MARK: - XML解析需要的素材
//1.可变数组
@property(nonatomic,strong)NSMutableArray * videos;
//2.当前解析的节点 -- 模型
@property(nonatomic,strong)Video * currentVideo;

//3.拼接字符串  -- 可变字符串
@property(nonatomic,strong)NSMutableString * elementStr;

@end

@implementation ViewController

//MARK: - 懒加载
-(NSMutableArray *)videos{
    if (!_videos) {
        _videos = [NSMutableArray array];
    }
    return _videos;
}

-(NSMutableString *)elementStr{
    if (!_elementStr) {
        _elementStr =[NSMutableString string];
    }
    return _elementStr;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    //加载数据
    [self loadData];
}

//MARK: - XML解析
-(void)loadData{
    //1.url
    NSURL * url = [NSURL URLWithString:@"http://127.0.0.1/videos.xml"];
    //2.request
    NSURLRequest * request = [NSURLRequest requestWithURL:url cachePolicy:1 timeoutInterval:10.0];
    //3.发送请求
    //使用新建队列,保证所有的XML解析工作再后台完成
    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        //XML解析 -- 耗时操作
       NSXMLParser * parser =  [[NSXMLParser alloc]initWithData:data];
        //设置代理- 一旦解析器开始解析,后续的工作都是通过代理来监听实现的
        parser.delegate = self;
        //解析XML
        [parser parse];
    }];
}

#pragma mark - <XML解析的代理方法>
//1.打开文档
-(void)parserDidStartDocument:(NSXMLParser *)parser{
    NSLog(@"1.开始文档");
    //清空数组
    [self.videos removeAllObjects];
}
//2.开始节点(Element - 元素) attributeDict 包含在开始节点内的拓展属性
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{
    NSLog(@"2.开始节点 %@ %@",elementName,attributeDict);
    //如果element 是video
    if ([elementName isEqualToString:@"video"]) {
        //新建video对象
        self.currentVideo = [[Video alloc]init];
        //设置videoId 属性 @()包装成NSNumber
        self.currentVideo.videoId = @([attributeDict[@"videoId"] intValue]);
    }
}
//3.发现节点内容(一个节点的内容,可能会读取很多次!) string(内容)
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    NSLog(@"3.发现节点内容==> %@",string);
    //拼接字符串
    [self.elementStr appendString:string];
}
//4.结束节点
-(void)parser:(NSXMLParser *)parser didEndElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName{
    NSLog(@"4.结束节点 %@ %@",elementName,namespaceURI);
    //如果是name length imageURL desc video
    if ([elementName isEqualToString:@"video"]) {
        //如果是video 就添加模型到数组
        [self.videos addObject:self.currentVideo];
    }else if ([elementName isEqualToString:@"name"]){
        self.currentVideo.name = self.elementStr;
    }else if ([elementName isEqualToString:@"length"]){
        self.currentVideo.length = @(self.elementStr.intValue);
    }else if ([elementName isEqualToString:@"videoURL"]){
        self.currentVideo.videoURL = self.elementStr;
    }else if ([elementName isEqualToString:@"imageURL"]){
        self.currentVideo.imageURL = self.elementStr;
    }else if ([elementName isEqualToString:@"desc"]){
        self.currentVideo.desc = self.elementStr;
    }else if ([elementName isEqualToString:@"teacher"]){
        self.currentVideo.teacher = self.elementStr;
    }
    //清空字符串
    [self.elementStr setString:@""];
}
//5.结束文档
-(void)parserDidEndDocument:(NSXMLParser *)parser{
    NSLog(@"5.结束文档 %@",self.videos);
}
//6.出现错误(只要是网络开发,就需要处理错误!!)
-(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
    NSLog(@"6.发生错误 %@",parseError);
}

@end

使用kvc优化4.结束节点代码

//4.结束节点
/*
 KVC 键值编码  cocoa 大招
 */
-(void)parser:(NSXMLParser *)parser didEndElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName{
    NSLog(@"4.结束节点 %@ %@",elementName,namespaceURI);
    //如果是name length imageURL desc video 
    if ([elementName isEqualToString:@"video"]) {
                //如果是video 就添加模型到数组
         [self.videos addObject:self.currentVideo];
    }else if (![elementName isEqualToString:@"videos"]){
        [self.currentVideo setValue:self.elementStr forKey:elementName];
    }
    //清空字符串
    [self.elementStr setString:@""];
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值