Json和XML解析
NSXMLParse
关于XML,有两种解析方式,分别是SAX(Simple API for XML,基于事件驱动的解析方式,逐行解析数据,采用协议回调机制)和DOM(Document Object Model ,文档对象模型。解析时需要将XML文件整体读入,并且将XML结构化成树状,使用时再通过树状结构读取相关数据,查找特定节点,然后对节点进行读或写)。苹果官方原生的NSXMLParse类库采用第一种方式,即SAX方式解析XML,它基于事件通知的模式,一边读取文档一边解析数据,不用等待文档全部读入以后再解析,所以如果你正打印解析的数据,而解析过程中间出现了错误,那么在错误节点之间的数据会正常打印,错误后面的数据不会被打印。解析过程由NSXMLParserDelegate协议方法回调。
插句题外话先,我在写这种方式解析XML数据的Demo时折腾了整整一天,说起来都有些不好意思了。程序运行的时候一直出现不能完成解析的情况,各种查各种试,真的是整了整整一天的时间。就在崩溃的边缘的时候,我竟然发现在我自己写XML文件时少写了一个“/。。。瞬间感觉整个世界都崩塌了。所以特地记下来警示自己也顺便给大家提个醒,在这种低级失误上浪费整整一天的时间,要多不值有多不值。谨记,谨记。
我们遵循MVC,首先我们创建模型,新建一个person类,存放XML文件中描述的person属性。再来一个解析XML文件的工具类XMLUtil,我们在里面实现文件的获取,代理方法的实现。
先来看这两个类的代码:
//person.h
#import <Foundation/Foundation.h>
@interface person : NSObject
@property (nonatomic, copy) NSString *pid;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *sex;
@property (nonatomic, copy) NSString *age;
@end
//XMLUtil.h
#import <Foundation/Foundation.h>
#import "person.h"
//声明代理
@interface XMLUtil : NSObject<NSXMLParserDelegate>
//添加属性
@property (nonatomic, strong) NSXMLParser *par;
@property (nonatomic, strong) person *person;
//存放每个person
@property (nonatomic, strong) NSMutableArray *list;
//标记当前标签,以索引找到XML文件内容
@property (nonatomic, copy) NSString *currentElement;
//声明parse方法,通过它实现解析
-(void)parse;
@end
//XMLUtil.m
#import "XMLUtil.h"
@implementation XMLUtil
- (instancetype)init{
self = [super init];
if (self) {
//获取事先准备好的XML文件
NSBundle *b = [NSBundle mainBundle];
NSString *path = [b pathForResource:@"test" ofType:@".xml"];
NSData *data = [NSData dataWithContentsOfFile:path];
self.par = [[NSXMLParser alloc]initWithData:data];
//添加代理
self.par.delegate = self;
//初始化数组,存放解析后的数据
self.list = [NSMutableArray arrayWithCapacity:5];
}
return self;
}
//几个代理方法的实现,是按逻辑上的顺序排列的,但实际调用过程中中间三个可能因为循环等问题乱掉顺序
//开始解析
- (void)parserDidStartDocument:(NSXMLParser *)parser{
NSLog(@"parserDidStartDocument...");
}
//准备节点
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(NSDictionary<NSString *, NSString *> *)attributeDict{
self.currentElement = elementName;
if ([self.currentElement isEqualToString:@"student"]){
self.person = [[person alloc]init];
}
}
//获取节点内容
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([self.currentElement isEqualToString:@"pid"]) {
[self.person setPid:string];
}else if ([self.currentElement isEqualToString:@"name"]){
[self.person setName:string];
}else if ([self.currentElement isEqualToString:@"sex"]){
[self.person setSex:string];
}else if ([self.currentElement isEqualToString:@"age"]){
[self.person setAge:string];
}
}
//解析完一个节点
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName{
if ([elementName isEqualToString:@"student"]) {
[self.list addObject:self.person];
}
self.currentElement = nil;
}
//解析结束
- (void)parserDidEndDocument:(NSXMLParser *)parser{
NSLog(@"parserDidEndDocument...");
}
//外部调用接口
-(void)parse{
[self.par parse];
}
@end
OK,总算是大功告成,如果对代理的使用比较熟悉的话,这部分内容其实还蛮简单的。如果被代码转来转去弄晕了的话可以在每个block的最后都加一个打印输出,做好标记,你就能弄懂程序的执行顺序了。
我们点击NSXMLParse,有了!

GDataXML
来看GDataXML,它是一种DOM方式的解析类库。DOM实现的原理是把整个xml文档一次性读出,放在一个树型结构里。在需要的时候,查找特定节点,然后对节点进行读或写。
在使用之前呢,我们还是先从网上下载GDataXML包,里面两个文件GDataXMLNode.h和GDataXMLNode.m导入到项目中来,编译,发现报错了,这是因为GDataXML是依赖libmxl2的,我们要去项目的Target中做一些设置。
- 找到项目的Tarfet,进入Build Phases里面的Link Binary With Libraries,点击“加号”,搜索libxml,把出现的包添加进去,这里最新版的XCode7和iOS9中,是libxml.2.2.tbd。
- 再来到Build Settings,我们可以搜索一下,找到Header Search Paths,添加路径“/usr/include/libxml2”。
- 再找到Other Link Flags,添加“-libxml2“
- 还有就是如果你下载的GDataXML是不支持ARC的,那么你就要像上面那样去添加“-fno-objc-arc”,这个视你下载的GDataXML包版本而定。
再次编译,就顺利通过了。
接下来看看我们怎么用这个东西。贴代码之前我真的想说一句,比起苹果原生的类库,这些开源的第三方类库真的在用起来的时候不知道有多舒服,懒人必备啊。在实际的开发中可以为我们节省很多的时间与精力,但是还是要搞懂人家原生的东西,这样才叫学会了么。
//ViewController.m
- (IBAction)GDataXML:(id)sender {
NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"xml"];
NSData *data = [[NSData alloc]initWithContentsOfFile:path];
//对象初始化
GDataXMLDocument *doc = [[GDataXMLDocument alloc]initWithData:data error:nil];
//获取根节点
GDataXMLElement *rootElement = [doc rootElement];
//获取其他节点
NSArray *students = [rootElement elementsForName:@"student"];
//初始化可变数组,用来显示到textView
self.GDatatext = [[NSMutableString alloc]initWithString:@""];
for (GDataXMLElement *student in students) {
//获取节点属性
GDataXMLElement *pidElement = [[student elementsForName:@"pid"] objectAtIndex:0];
NSString *pid = [pidElement stringValue];
GDataXMLElement *nameElement = [[student elementsForName:@"name"] objectAtIndex:0];
NSString *name = [nameElement stringValue];
GDataXMLElement *sexElement = [[student elementsForName:@"sex"] objectAtIndex:0];
NSString *sex = [sexElement stringValue];
GDataXMLElement *ageElement = [[student elementsForName:@"age"] objectAtIndex:0];
NSString *age = [ageElement stringValue];
//调整一下姿势,添加到可变长字符串~~
NSString *t = [NSString stringWithFormat:@"学号:%@ 姓名:%@ 性别:%@ 年龄:%@\n", pid, name, sex, age];
[self.GDatatext appendString:t];
}
self.textView.text = self.GDatatext;
}
就一段,是不是看起来非常的舒服呢!
跑一下,跟我们刚才使用的NSXMLParse是不是一样呢?
哈,搞定!
XML解析总结
上述两种解析用到的类库分别代表了两种典型的XML数据解析方式,SAX和DOM,各有优势,比如在应对比较大数据量的XML文件时,后者由于需要先读取整个文档,性能和速度上就必然不及前者了。
其实现在在实际应用中XML已经越来越少了,但是说起iOS中的网络编程,就免不了和XML格式的数据打交道。还有就是,我们在这里仅仅介绍了两种常用的XML解析方式,如同解析Json数据一样,解析XML文件也有很多种方法,除了上述两种,还有比如像TBXML, TouchXML, KissXML, TinyXML等等,具体的使用方法可以去Github上找,都有使用方法的说明的。
原文链接:http://www.jianshu.com/p/a54d367adb2a
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
Json和XML解析的更多相关文章
- 【.Net 】Json和Xml解析
引言 Json和Xml是现在跨平台传输数据的主流格式,关于它们的解析,网上资料很多,我稍作整理,写成一个小demo,方便日后使用. JSON解析 能进行json解析的类库有很多,例如Ja ...
- iOS - - JSON 和 XML解析
JSON 和 XML 一.JSON 1.什么是JSON JSON是一种轻量级的数据格式,一般用于数据交互 服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外) 2.JSON的格 ...
- 网络HTTP、JSON、XML解析等 复习
一.一个HTTP请求的基本要素1.请求URL:客户端通过哪个路径找到服务器 2.请求参数:客户端发送给服务器的数据* 比如登录时需要发送的用户名和密码 3.返回结果:服务器返回给客户端的数据* 一般是 ...
- JSON、XML 解析
iOS开发--XML/JSON数据解析 不错的文章http://www.jianshu.com/p/a54d367adb2a
- iOS - 分析JSON、XML的区别和解析方式的底层是如何实现的(延伸实现原理)
<分析JSON.XML的区别,JSON.XML解析方式的底层是如何实现的(延伸实现原理)> (一)JSON与XML的区别: (1)可读性方面:基本相同,XML的可读性比较好: (2)可扩展 ...
- iOS XML解析使用-韩国庆
欢迎-------(北京-iOS移动开发金牌教师QQ:2592675215)韩老师给你带来XML解析课程 今天给大家讲解下xml解析的第三方简单用法:首先我解释下,json和xml解析格式. JSON ...
- JSON解析和XML解析对比
JSON解析和XML解析是较为普遍的两种解析方式,其中JSON解析的市场分额更大.本文系统的分析两种解析方式的区别,为更好地处理数据作准备.由于目前阶段主要是做移动开发,所以本文所描述的JSON解析和 ...
- iOS-数据持久化基础-JSON与XML数据解析
解析的基本概念 所谓“解析”:从事先规定好的格式串中提取数据 解析的前提:提前约定好格式.数据提供方按照格式提供数据.数据获取方按照格式获取数据 iOS开发常见的解析:XML解析.JSON解析 一.X ...
- iOS开发——网络篇——JSON和XML,NSJSONSerialization ,NSXMLParser(XML解析器),NSXMLParserDelegate,MJExtension (字典转模型),GDataXML(三方框架解析XML)
一.JSON 1.JSON简介什么是JSONJSON是一种轻量级的数据格式,一般用于数据交互服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外) JSON的格式很像OC中的字典 ...
随机推荐
- 《GPU高性能编程CUDA实战》第七章 纹理内存
▶ 本章介绍了纹理内存的使用,并给出了热传导的两个个例子.分别使用了一维和二维纹理单元. ● 热传导(使用一维纹理) #include <stdio.h> #include "c ...
- SqlServer——触发器
一:触发器基本知识 1.首先必须明确以下几点: 触发器是一种特殊的存储过程,但没有接口(输入输出参数),在用户执行Inserted.Update.Deleted 等操作时被自动触发: 当触发的SQL ...
- node 图片上传功能
node 代码: var http = require("http"); var express = require('express') app = express(), for ...
- The type org.springframework.dao.support.DaoSupport cannot be resolved. It is indirectly referenced
springmvc mybatis整合,遇到错误:The type org.springframework.dao.support.DaoSupport cannot be resolved. It ...
- span width不起作用,border 无效
span属于内联元素,因此width对内联元素不起作用. 需要设置display:inline-block;使其成为内联级块级元素: border不起作用,主要是未设置border-style:sol ...
- Maven可执行jar包
参考文章: Maven生成可以直接运行的jar包的多种方式(http://blog.csdn.net/xiao__gui/article/details/47341385) 一般,我们通过 > ...
- 7 python 类的组合
1.组合与重用性 软件重用的重要方式除了继承之外还有另外一种方式,即:组合 组合指的是,在一个类中以另外一个类的对象作为 1.一个类的属性可以是一个类对象,通常情况下在一个类里面很少定义一个对象就是它 ...
- 一本很好的书LearnOpenGL
这本书好像不怎么出名,但读起来非常易懂,知识全面 https://learnopengl.com/Advanced-Lighting/Normal-Mapping 基于物理的渲染 – 理论篇 < ...
- 【348】通过 Numpy 创建各式各样的矩阵
参考:NumPy之array-一个程序媛的自我修养-51CTO博客 参考:numpy中数组和矩阵的区别 - jiangsujiangjiang的博客 - CSDN博客 一.使用系统方法 二.用指定的数 ...
- one by one 项目 part 4
出现异常”The last packet sent successfully to the server was 0 milliseconds ago.“的大部分原因是由于数据库回收了连接,而系统的缓 ...