XML简介

  • XML出身名门,W3C制定,微软和IBM曾经共同大力推荐过的数据格式.
  • XML指可扩展标记语言(Extensible Markup Language).
  • 被设计用来传输和存储数据.在以前是常用的数据格式.
  • 对比 : HTML超文本标记语言,是设计用来显示网页的.并不是保存数据和传输的方式.

XML格式

  • XML由标记组成,xml的标记是可扩展的,没有预定义.
  • <tag>这就是标记.有开始标记和结束标记.例如 <tag>表示开始标记,</tag>表示结束标记.是成对出现的.
  • 注意 : 一个XML文件有且只有一个节点(标签).

XML演练

  • 新建一个empty空文件,取名demo.xml
<!-- 描述几个学生 -->
<Class><!-- 用name和age标签描述学生 --><student><name>卡特琳娜</name><age>21</age></student><student><name>牛头</name><age>22</age></student><!-- 标签中定义属性也可以描述学生 --><student name="卡尔萨斯" age="23"></studet><!-- 标签中定义属性描述学生的简写 --><student name="瑞兹" age="24" /></Class>

XML文件解析方式

  • 如果想获取到XML文件中保存的数据,需要将XML文件中的数据解析出来.
  • SAX方式解析和DOM方式解析

SAX方式解析XML

  • 苹果官方提供的原生的解析XML文件的方式
  • 在iOS上解析XML文件的方式.
  • 速度快,内存占用小.
  • 是只读的,只能读取XML文件数据不能做修改操作.

DOM方式解析XML

  • 是在MAC使用的解析方式.
  • 注意 : 内存消耗极大,不适用于手机.
  • 可以读写XML文件.
  • iPhone无法直接使用DOM方式解析XML.
  • 如果要在iPhone上使用DOM方式解析XML文件,可以使用第三方框架.

XML解析之SAX解析

SAX方式解析XML步骤

  • 创建XML文件解析器.
  • 遵守解析器的代理协议.
  • 启动解析器,开始解析.

XML文件的解析是在代理方法中完成的.需要实现以下代理方法.

1.开始解析`XML`文件.
2.找开始节点(标签).
3.找节点之间的内容.
4.找结束节点.
5.结束解析`XML`文件.
6.监听`XML`文件是否解析出错.

SAX方式解析XML实现

  • 1.发送网络请求,获取二进制的XML数据.
/// 下载二进制的XML数据
- (void)downloadXML
{// 获取URLNSURL *url = [NSURL URLWithString:@"http://localhost/videos.xml"];// 创建请求NSURLRequest *request = [NSURLRequest requestWithURL:url];// 发送异步请求,请求自建服务器中的demo.json数据[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {// 判断链接是否错误if (connectionError) {NSLog(@"链接错误 %@",connectionError);return;}// 检查响应体是否有错NSHTTPURLResponse *HTTPURLResponse = (NSHTTPURLResponse *)response;if (HTTPURLResponse.statusCode == 200 || HTTPURLResponse.statusCode == 304) {NSLog(@"二进制的XML数据 %@",data);} else {NSLog(@"服务器内部错误");return;}}];
}

  • 2.拿到二进制的XML数据之后,创建XML解析器,设置代理,启动解析器.
// 创建XML解析器
NSXMLParser *XMLParser = [[NSXMLParser alloc] initWithData:data];
// 设置解析器代理协议
XMLParser.delegate = self;
// 开始解析
[XMLParser parse];

  • 3.实现代理方法
// 1.开始解析文档
- (void)parserDidStartDocument:(NSXMLParser *)parser
{NSLog(@"1.开始解析文档 %@",[NSThread currentThread]);
}// 2.找开始节点
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict
{// elementName : 开始节点// attributeDict : 节点属性NSLog(@"2.找开始节点 %@--%@",elementName,attributeDict);
}// 3.找节点之间的内容
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{// string : 节点之间的内容.NSLog(@"3.找节点之间的内容 %@",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(@"6.监听解析是否出错 %@",parseError);
}

结论

  • 通过代理方法中的NSLog,可以了解到解析XML文件中数据的过程.
  • 以上步骤,2--->3--->4,会不断循环,一直到所有数据解析完成.
  • 节点之间的内容并不是一次就能找全的,有时候需要循环多次才能找全.
  • 如果解析数据量非常大的XML文件是很耗时的.当在哪个线程设置了代理协议,就在哪个线程中解析.

XML解析之转模型

准备模型类

  • .h文件中的声明
@interface VideoModel : NSObject/// 视频编号
@property (nonatomic,copy) NSString *videoId;
/// 视频名称
@property (nonatomic,copy) NSString *name;
/// 视频长度
@property (nonatomic,copy) NSString *length;
/// 视频链接
@property (nonatomic,copy) NSString *videoURL;
/// 视频图标
@property (nonatomic,copy) NSString *imageURL;
/// 视频标题
@property (nonatomic,copy) NSString *desc;
/// 视频作者
@property (nonatomic,copy) NSString *teacher;/// 字典转模型 : 解析XML的时候,没有字典,所以这个不需要
//+ (instancetype)videoWithDict:(NSDictionary *)dict;@end/*<video videoId="1"><name>01.C语言-语法预览</name><length>320</length><videoURL>/itcast/videos/01.C语言-语法预览.mp4</videoURL><imageURL>/itcast/images/head1.png</imageURL><desc>C语言-语法预览</desc><teacher>李雷</teacher></video>*/

  • .m文件中的实现
@implementation VideoModel/// 无用处
+ (instancetype)videoWithDict:(NSDictionary *)dict
{// 创建模型对象VideoModel *v = [[VideoModel alloc] init];// KVC 字典转模型[v setValuesForKeysWithDictionary:dict];// 返回模型对象return v;
}/// 打印模型的详细内容
- (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

解析XML文件

XML文件中的数据读取出来,转换成可以直接使用的模型数据.

  • XML数据转模型数据的准备工作
@interface ViewController () <NSXMLParserDelegate>/// video对应的模型对象
@property (nonatomic,strong) VideoModel *currentVideo;
/// 拼接节点之间内容的字符串
@property (nonatomic,copy) NSMutableString *stringM;
/// 模型数组
@property (nonatomic,strong) NSMutableArray *videoM;@end@implementation ViewController- (NSMutableString *)stringM
{if (_stringM == nil) {_stringM = [NSMutableString string];}return _stringM;
}- (NSMutableArray *)videoM
{if (_videoM == nil) {_videoM = [NSMutableArray array];}return _videoM;
}

实现代理方法

  • 1.开始解析文档
- (void)parserDidStartDocument:(NSXMLParser *)parser
{NSLog(@"1.开始解析文档 %@",[NSThread currentThread]);
}

  • 2.找开始节点
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict
{// elementName : 开始节点// attributeDict : 节点属性NSLog(@"2.找开始节点 %@--%@",elementName,attributeDict);// 每找到一个video节点(标签),就创建一个对应的模型对象if ([elementName isEqualToString:@"video"]) {// 创建video标签对应的模型对象self.currentVideo = [[VideoModel alloc] init];// 拿到标签的属性,可以给模型的videoId属性赋值self.currentVideo.videoId = attributeDict[@"videoId"];// 将模型对象添加到模型数组中[self.videoM addObject:self.currentVideo];}
}

  • 3.找节点之间的内容
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{// string : 节点之间的内容.(内容不会一次性找全)NSLog(@"3.找节点之间的内容 %@",string);// 拼接节点之间的字符串[self.stringM appendString:string];
}

  • 4.找结束节点

  • 注意 : 在KVC给模型的属性赋值的过程中,一定要排除videosvideo两个节点.因为这两个节点不需要转模型,且在模型类中没有对应的属性值.不排除掉,KVC在赋值过程中程序会崩溃.

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{NSLog(@"4.找结束节点 %@",elementName);// 找到了结束节点,说明节点之间的内容已经获取到了,就可以给模型的属性赋值了// 如果要在这个方法里面获取到模型,那么模型需要定义成全局的// 一定要排除`videos`和`video`两个节点,这两个节点不需要转模型if (![elementName isEqualToString:@"videos"]&&![elementName isEqualToString:@"video"]) {[self.currentVideo setValue:self.stringM forKey:elementName];}
}

  • 5.结束解析文档
- (void)parserDidEndDocument:(NSXMLParser *)parser
{NSLog(@"5.结束解析文档");// 打印全部模型NSLog(@"%@",self.videoM);
}

  • 6.监听解析是否出错
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{NSLog(@"6.监听解析是否出错 %@",parseError);
}

结论

  • 不能按照字典转模型的逻辑来处理XML转模型.解析XML数据的过程中没有字典.

  • 每个video标签就是描述一个视频的.每个模型对象也是用来描述一个视频的.所以每找到一个video标签就要创建一个对应的模型对象.模型对象属性赋值会在多个代理方法中进行赋值.所以需要定义成全局的模型对象.

  • 节点之间的内容有时候不会一次性就找全,所以需要多次拼接字符串,而且要在找结束节点代理方法中使用,所以也要定义成全局的可变字符串.

  • 为了能够打印出所有的模型对象,需要将模型对象添加到数组中.

清空供拼接的可变字符串

// 4.找结束节点
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{NSLog(@"4.找结束节点 %@",elementName);// 找到了结束节点,说明节点之间的内容已经获取到了,就可以给模型的属性赋值了// 如果要在这个方法里面获取到模型,那么模型需要定义成全局的// 一定要排除`videos`和`video`两个节点,这两个节点不需要转模型if (![elementName isEqualToString:@"videos"]&&![elementName isEqualToString:@"video"]) {[self.currentVideo setValue:self.stringM forKey:elementName];}// 给模型属性赋值完成之后,需要清空字符串.[self.stringM setString:@""];
}

XML解析之DOM解析

  • 仅做了解.

DOM简介

  • DOM : Document Object Model
  • DOM : 文档对象模型 (文档模型)
  • 一次性把XML文件全部加载到内存,内存消耗大,适合读写比较小的XML文件.
  • 之前的SAX方式只能读取XML文件,但是DOM方式可以修改XML文件,包括添加删除修改节点.
  • iOS系统默认不支持DOM解析,在iOS系统下解析DOM的话需要第三方框架.
  • 第三方框架 : GData/KissXML(XMPP中使用此框架)

GData中类的关系分析

集成GData框架

  • 导入GDataXMLNode第三方文件.
  • 解决GData的报错.

GData解析XML的步骤

1.获取XML文档.
2.获取XML文档的根标签.
3.遍历根标签,获取根标签的子标签(video标签),创建video标签对应的模型对象.
4.遍历video标签,获取video标签的子标签,给模型对象的属性赋值.
5.遍历video标签,获取video标签的属性,给模型对象的videoId属性赋值.

GData解析XML的实现

  • 模型类没有变化,还是SAX方式解析的那个模型类.
  • 从网络中获取到XML文件的二进制数据.
  • 代码实现 :
/// DOM方式解析XML
- (void)DOM:(NSData *)data
{
    // 1.获取XML文档
    GDataXMLDocument *XMLDocument = [[GDataXMLDocument alloc] initWithData:data error:NULL];

// 2.获取XML文档的根标签
    GDataXMLElement *rootElement = XMLDocument.rootElement;

// 创建模型数组,将模型对象添加到模型数组中
    NSMutableArray *videoM = [NSMutableArray array];

// 3.遍历根标签,获取根标签的子标签(video标签),创建video标签对应的模型对象
    for (GDataXMLElement *videoElement in rootElement.children) {

// 创建video标签对应的模型对象
        VideoModel *video = [[VideoModel alloc] init];
        // 将模型对象添加到模型数组中
        [videoM addObject:video];

// 4.遍历video标签,获取video标签的子标签,给模型对象的属性赋值
        for (GDataXMLElement *subElement in videoElement.children) {
            // KVC给模型的属性赋值
            [video setValue:subElement.stringValue forKey:subElement.name];
        }

// 5.遍历video标签,获取video标签的属性,给模型对象的videoId属性赋值
        NSLog(@"%@",[videoElement.attributes class]);
        for (GDataXMLNode *attr in videoElement.attributes) {
            // KVC给模型的videoId属性赋值
            [video setValue:attr.stringValue forKey:attr.name];
        }
    }

NSLog(@"%@",videoM);
}

iOS XML浅谈相关推荐

  1. 【转】从Mac/OS和iOS开放源码浅谈UNIX家谱

    [转]从Mac/OS和iOS开放源码浅谈UNIX家谱 阅读数:1245 苹果公司在各类开源项目中长期贡献着自己的力量,但其UNIX系统技术一直都属于闭源阵营(这一点可以从NUX OS阵营和家谱图中得到 ...

  2. iOS之浅谈纯代码控制UIViewController视图控制器跳转界面的几种方法

    一.最普通的视图控制器UIViewContoller 一个普通的视图控制器一般只有模态跳转的功能(ipad我不了解除外,这里只说iPhone),这个方法是所有视图控制器对象都可以用的,而实现这种功能, ...

  3. iOS 送审浅谈:1.4.1、2.1、2.5.2、2.5.4、4.2.3、5.2.5

    目录 Guideline 1.4.1 - Safety - Physical Harm Guideline 2.1 - Information Needed: Guideline 2.1 - Info ...

  4. ios多线程浅谈和使用

    多线程一直是很操蛋的一个话题,其实如果你理解了很简单,没理解很麻烦:在OC中多线程通常有以下四种 四种线程 pthread_t ,NSThread, GCD,NSOperation+NSOperati ...

  5. iOS实录15:浅谈iOS Crash

    导语:在当前的iOS开发中,虽然ARC为开发者解决了手动内存管理时代 的许多麻烦,但是内存方面的问题依然是产生iOS Crash的元凶之一,本文介绍内存方面,有关僵尸对象.野指针.内存泄漏.废弃内存这 ...

  6. Unity iOS打开AppStore评星页面,浅谈Application.OpenURL()方法。

    http://fairwoodgame.com/blog/?p=38 Unity iOS打开AppStore评星页面,浅谈Application.OpenURL()方法. Posted in  Uni ...

  7. iOS 自定义转场动画浅谈

    代码地址如下: http://www.demodashi.com/demo/11612.html 路漫漫其修远兮,吾将上下而求索 前记 想研究自定义转场动画很久了,时间就像海绵,挤一挤还是有的,花了差 ...

  8. iOS 核心动画 Core Animation浅谈

    代码地址如下: http://www.demodashi.com/demo/11603.html 前记 关于实现一个iOS动画,如果简单的,我们可以直接调用UIView的代码块来实现,虽然使用UIVi ...

  9. 浅谈 unix, linux, ios, android 区别和联系

    浅谈 unix, linux, ios, android 区别和联系 网上的答案并不是很好,便从网上整理的相对专业的问答. 1.UNIX 和 Linux UNIX 操作系统(尤尼斯), 是一个强大的多 ...

最新文章

  1. 【转发】什么时候该用委托,为什么要用委托,委托有什么好处
  2. MySql存储引擎特性对比
  3. 【转】Android开发中adb启动失败adb连接异常的解决办法 offline
  4. linux搭建交换机日志,用LINUX的SYSLOG做交换机、路由器的日志服务器
  5. 无法创建ssis数据流任务_SSIS中的数据分析任务概述
  6. 风变python学习2---字符串,整数,浮点型数据分析,应用
  7. PHP之mb_convert_case使用
  8. URLDecoder解码异常 URLDecoder: Illegal hex characters in escape (%) pattern - For input string: “xxx“
  9. php apache 假死,解决apache兼容性及慢或假死问题
  10. aid learning安装应用_Aid Learning
  11. 2023年重庆邮电大学计算机科学与技术(802)初试经验贴
  12. win7计算机双击变管理,如何修复Win7系统鼠标单击以双击
  13. 如何避免搜索引擎爬虫产生的流量过大以及搜索引擎设置优化
  14. 虚幻引擎/UE4离线安装
  15. qlib平台实现可转债“双低”策略
  16. java join的用法
  17. 分享电脑便捷妙招,电脑小白们快码住
  18. 2021-2027全球及中国401(k)软件行业研究及十四五规划分析报告
  19. 【C语言】memset函数用法
  20. 图片添加高斯噪声和椒盐噪声python

热门文章

  1. (二)目标检测模型的评测与训练技巧
  2. JavaScript添加数据
  3. mysql用month()函数取月份时,不足10的前面补0
  4. php json schema,JSON Schema Validation介绍
  5. 计算机作文点评,中学生作文点评:《你是我最温暖的人》,文章于平凡小事中见真情...
  6. [SinGuLaRiTy] NOIP互测模拟赛
  7. Mac启动/关闭Redis服务器
  8. COMSOL离散数据的插值拟合,并对插值函数特定点求值求积分
  9. HOOK之APIhook(转)
  10. WebRTC -- 流媒体基础概念