文档章节

XML 介绍

就不穿小内
 就不穿小内
发布于 2015/12/26 17:34
字数 1191
阅读 8
收藏 0


  • XML的特点,出身名门,W3C制定,微软和IBM曾经共同大力推荐过的数据格式

  • XML 指可扩展标记语言(eXtensible Markup Language)

  • 被设计用来传输和存储数据

  • HTML 是设计用来表示页面的

XML 解析的方式

DOM 解析

  • 是在 MAC 使用的解析方式

  • 内存消耗极大,不适用于手机

  • iPhone无法直接使用 DOM 方式解析 XML

SAX 解析

  • 是只读的方式,从上向下的方式解析

  • 是苹果提供的解析方式

  • 速度快

  • NSXMLParser 通过代理实现解析

SAX 解析步骤

  1. 开始文档 - 准备工作

  2. 开始"节点"

  3. 发现节点内部的内容,每一个节点,可能需要多次才能找完

  4. 结束"节点"

  5. 结束文档 - 解析结束


以上步骤,2,3,4,会不断循环,一直到所有解析完成



加载 XML 数据

loadData

- (void)loadData {    NSURL *url = [NSURL URLWithString:@"http://localhost/videos.xml"];    NSURLRequest *request = [NSURLRequest requestWithURL:url];    // 异步解析 XML
    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {        // 1. 使用网络返回的二进制数据实例化 NSXMLParser 对象
        NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];        // 2. 设置代理,通过代理方法实现 SAX 解析
        parser.delegate = self;        // 3. 开始解析
        [parser parse];
    }];
}

代理方法 - 添加 Log 确认思路

// MARK: - NSXMLParserDelegate// 1. 开始文档 - 准备工作- (void)parserDidStartDocument:(NSXMLParser *)parser {    NSLog(@"1. 开始文档");
}// 2. 开始节点- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {    NSLog(@"2. 开始节点 %@ %@", elementName, attributeDict);
}// 3. 发现文字- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {    NSLog(@"==> %@", string);
}// 4. 结束节点- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {    NSLog(@"4. 结束节点 %@", elementName);
}// 5. 结束文档 - 解析结束- (void)parserDidEndDocument:(NSXMLParser *)parser {    NSLog(@"5. 解析结束");
}// 6. 错误处理- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {    NSLog(@"解析错误 %@", parseError);
}

整理思路,确定素材

video 模型

@interface Video : NSObject///  视频代号@property (nonatomic, copy) NSNumber *videoId;///  视频名称@property (nonatomic, copy) NSString *name;///  视频长度@property (nonatomic, copy) NSNumber *length;///  视频URL@property (nonatomic, copy) NSString *videoURL;///  图像URL@property (nonatomic, copy) NSString *imageURL;///  介绍@property (nonatomic, copy) NSString *desc;///  讲师@property (nonatomic, copy) NSString *teacher;

+ (instancetype)videoWithDict:(NSDictionary *)dict;@end

确定素材

///  目标模型数组@property (nonatomic, strong) NSMutableArray *videos;///  当前解析对象@property (nonatomic, strong) Video *currentVideo;///  拼接字符串@property (nonatomic, strong) NSMutableString *elementString;

懒加载

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

- (NSMutableString *)elementString {
    if (_elementString == nil) {
        _elementString = [[NSMutableString alloc] init];
    }
    return _elementString;

}


XML 解析

// 1. 开始文档 - 准备工作- (void)parserDidStartDocument:(NSXMLParser *)parser {    NSLog(@"1. 开始文档");
    [self.videos removeAllObjects];
}// 2. 开始节点- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {    NSLog(@"2. 开始节点 %@ %@", elementName, attributeDict);    if ([elementName isEqualToString:@"video"]) {        // 如果是 video 节点,新实例化一个 video 对象
        self.currentVideo = [[Video alloc] init];        // 设置 videoId 属性
        self.currentVideo.videoId = @([attributeDict[@"videoId"] integerValue]);
    }    // 清空字符串
    [self.elementString setString:@""];
}// 3. 发现文字- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {    NSLog(@"==> %@", string);
    [self.elementString appendString:string];
}// 4. 结束节点- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {    NSLog(@"4. 结束节点 %@", elementName);    if ([elementName isEqualToString:@"video"]) {        // 如果是 video 节点,说明一个节点解析完成,将 currentVideo 添加到数组
        [self.videos addObject:self.currentVideo];
    } else if (![elementName isEqualToString:@"videos"]) {        // 如果不是 videos 节点,说明是 video 的属性节点,利用 KVC 设置数值
        [self.currentVideo setValue:self.elementString forKey:elementName];
    }
}// 5. 结束文档 - 解析结束- (void)parserDidEndDocument:(NSXMLParser *)parser {    NSLog(@"5. 解析结束");    NSLog(@"%@ %@", self.videos, [NSThread currentThread]);
}

绑定表格

数据源

定义属性

///  表格的数据源数组@property (nonatomic, strong) NSArray *dataList;

setter方法

- (void)setDataList:(NSArray *)dataList {
   _dataList = dataList;

   [self.tableView reloadData];
}

数据源方法

#pragma mark - 数据源方法- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {    return self.dataList.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];    // 设置 Cell...
   cell.textLabel.text = [self.dataList[indexPath.row] name];    return cell;
}

设置数据源方法

// 5. 结束文档 - 解析结束- (void)parserDidEndDocument:(NSXMLParser *)parser {    NSLog(@"5. 解析结束");    NSLog(@"%@ %@", self.videos, [NSThread currentThread]);    dispatch_async(dispatch_get_main_queue(), ^{        self.dataList = self.videos;
   });
}

自定义 Cell

Copy 属性

视频时长属性

///  时间字符串@property (nonatomic, copy) NSString *timeString;

使用 getter 方法

- (NSString *)timeString {    int len = self.length.intValue;    return [NSString stringWithFormat:@"%02d:%02d:%02d", len / 3600, (len % 3600) / 60, len % 60];
}

利用 length 的 setter 方法

- (void)setLength:(NSNumber *)length {
   _length = length;    int len = length.intValue;
   _timeString = [NSString stringWithFormat:@"%02d:%02d:%02d", len / 3600, (len % 3600) / 60, len % 60];
}

修改 setter 方法

- (void)setLength:(NSNumber *)length {
   _length = [length copy];    int len = length.intValue;
   _timeString = [NSString stringWithFormat:@"%02d:%02d:%02d", len / 3600, (len % 3600) / 60, len % 60];
}


如果重写 copy 属性的 setter 方法,一定要使用 copy



重构

///  解析 Video XML 数据//////  @param parser   XML 解析器///  @param finished 完成回调+ (void)parserVideo:(NSXMLParser *)parser finished:(void (^)(NSArray *dataList))finished;
+ (void)parserVideo:(NSXMLParser *)parser finished:(void (^)(NSArray *))finished {
   VideoXMLParser *obj = [[self alloc] init];

   obj.finishedBlock = finished;
   parser.delegate = obj;
   [parser parse];
}

- (void)loadData {    NSURL *url = [NSURL URLWithString:@"http://localhost/videos.xml"];    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:15.0];

    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

        NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];

        [VideoXMLParser parserVideo:parser finished:^(NSArray *dataList) {            self.dataList = dataList;
        }];
    }];
}


© 著作权归作者所有

上一篇: PList 解析
下一篇: JSON 解析
就不穿小内
粉丝 4
博文 59
码字总数 32988
作品 0
海淀
私信 提问
源码推荐:xml解析成NSDictionary类似json framework用法

我一直觉得json比xml好,因为它比xml更轻量级。在开发当中,很多都采用的是xml,我不知道为什么。但用iOS SDK解析xml非常麻烦,用了json framework的人都知道解析json很简单,今天介绍的源码就...

长平狐
2012/08/13
142
0
XML 和 Java 技术JiBX 体系结构

文章转载出处:http://www.cnblogs.com/hoojo/archive/2011/04/27/2030205.html Jibx 处理XML 前面有介绍过json-lib这个框架,在线博文:http://www.cnblogs.com/hoojo/archive/2011/04/21/2......

17099933344
2017/08/03
0
0
android下通过xstream解析复杂的xml格式信息

在android下通过xstream解析xml格式信息一文中介绍了通过xstream解析比较简单的xml文件到相应的Java bean中,下面介绍带节点的xml文件,xml文件格式如下 <?xml version="1.0" encoding="utf-...

xiahuawuyu
2012/10/13
0
0
『XSD校验XML』使用java通过XSD校验XML文件

本文简单介绍使用java语言,通过XSD文件来校验XML文件结构。 XML和XSD介绍 XML文件:XML的全称是可扩展标记语言,是一种用于标记电子文件使其具有结构性的标记语言,可以按照约定的格式定义出...

dejunz
2016/11/08
0
0
Python使用ElementTree处理XML

原文出处:https://www.cnblogs.com/zqchen/articles/3936805.html ElementTree是Python常用的处理XML文件的类。下面将介绍使用ElementTree解析、查找、修改XML的方法。 一、引用方法 Elemen...

kuSorZ
2017/12/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

texlive安装

Installing to: D:/bin/texlive/texlive/2019Installing [001/307, time/total: ??:??/??:??]: adobemapping [2130k]Installing [002/307, time/total: 00:03/08:57]: ae [84k]Installing......

MtrS
今天
2
0
运维规范

命名规范 发布流程 监控告警 故障定位 状态 日志 监控

以谁为师
今天
2
0
约瑟夫环(报数游戏)java实现

开端 公司组织考试,一拿到考题,就是算法里说的约瑟夫环,仔细想想 以前老师将的都忘了,还是自己琢磨把~ package basic.gzy;import java.util.Iterator;import java.util.LinkedList;...

无极之岚
今天
3
0
Kernel字符设备驱动框架

Linux设备分为三大类:字符设备,块设备和网络设备,这三种设备基于不同的设备框架。相较于块设备和网络设备,字符设备在kernel中是最简单的,也是唯一没有基于设备基础框架(device结构)的...

yepanl
今天
3
0
Jenkins 中文本地化的重大进展

本文首发于:Jenkins 中文社区 我从2017年开始,参与 Jenkins 社区贡献。作为一名新成员,翻译可能是帮助社区项目最简单的方法。 本地化的优化通常是较小的改动,你无需了解项目完整的上下文...

Jenkins中文社区
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部