iOS 详解NSXMLParser方法解析XML数据方法
前一篇文章已经介绍了如何通过URL从网络上获取xml数据。下面介绍如何将获取到的数据进行解析。
下面先看看xml的数据格式吧!
- <?xml version="1.0" encoding="UTF-8"?>
- <Books>
- <Book id="1">
- <title>Circumference</title>
- <author>Nicholas Nicastro</author>
- <summary>Eratosthenes and the Ancient</summary>
- </Book>
- <Book id="2">
- <title>Copernicus Secret</title>
- <author>Jack Repcheck</author>
- <summary>How the scientific revolution began</summary>
- </Book>
- <Book id="3">
- <title>Angels and Demons</title>
- <author>Dan Brown</author>
- <summary>Robert Langdon is summoned to a Swiss</summary>
- </Book>
- </Books>
显然在这个xml中包括三本书的一些基本数据:id title author summary 解析的过程就是将这些数据提取出来。
先简单介绍一下xml数据解析吧。xml数据的解析一般有两种方式:SAX(Simple API for XML)和DOM (Document Object Model),事件和文档。
sax的实现方法和dom不同。他只在xml文档中查找特定条件的内容,并且只提取需要的内容。这样做占用内存小,灵活。
NSXMLParser 实现的是sax方法解析xml文件。
下面进入主题介绍如何对xml进行解析:
一、将上面的xml数据保存为Books.xml作为本地xml数据,并导入项目中。
二、由于book中含有几个属性,所以这里第一个book类。
Book.h文件:
- #import <Foundation/Foundation.h>
- @interface Book : NSObject
- @property (nonatomic, readwrite) NSInteger bookID;
- @property (nonatomic, retain) NSString *title;
- @property (nonatomic, retain) NSString *author;
- @property (nonatomic, retain) NSString *summary;
- @end
Book.m文件
- #import "Book.h"
- @implementation Book
- @synthesize bookID;
- @synthesize title;
- @synthesize author;
- @synthesize summary;
- @end
三、要实现对xml数据的解析实际上是通过实现NSXMLParserDelegate委托中的几个方法。
- #pragma mark xmlparser
- //step 1 :准备解析
- - (void)parserDidStartDocument:(NSXMLParser *)parser
- {
- }
- //step 2:准备解析节点
- - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
- {
- }
- //step 3:获取首尾节点间内容
- - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
- {
- }
- //step 4 :解析完当前节点
- - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
- {
- }
- //step 5:解析结束
- - (void)parserDidEndDocument:(NSXMLParser *)parser
- {
- }
- //step 6:获取cdata块数据
- - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock
- {
- }
在实现xml解析过程以上方法中的step3 、4、5是必须的,而step1、5可选。
下面分别介绍:
Step 1: 在开始解析之前的一些准备工作,例如初始化一些存储变量。在我的这个例子中,使用了一个Book实例变量来存储一本书(也即是一组信息),一个可变数组来存储这三本书(即每一组信息都当成这个数组中的一个元素),(此次要注意理解数据变量之间的关系),其他变量就暂不介绍啦(待会看源代码就可以了)。
Step 2: 当解析器遇到xml的根标签和一组信息的开始标签时就开始调用这个方法,在这个xml文件中,遇到Books(xml文件的根标签),Book(一组信息的开始标签)时就会调用这个方法。那么也就可以知道这个方法在程序运行过程中被调用了多次。那么就可以用 if 语句判断遇到的是Books还是Book,然后做一些相应的操作(具体的话待会看源代码)。
- - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
- {
- }
注意其中的参数:elementName表示遇到的标签,在这个程序中会遇到的是Books和Book; 解析到一个标签时,开始的 标签可能会有一些属性,例如在这里<Book id="1">
那么id就是属性啦,在这个方法中他是用一个字典来保存的即(NSDictionary *)attributeDict,那么对这个字典操作就可以得到你要的value和key啦。
Step 3:当解析器找到开始标签和结束标签之间的字符时,就调用这个方法,读取其中的内容。 注意:这里读取到的string在这个函数里面我们并不知道是那个属性的内容,意思就是假如string的内容是Circumference(Book 的title),但是我们不知道这个是title的内容;那么在哪里才知道,然后对它进行存储操作呢,不要着急,就是Step4啦!
Step 4:当解析器读到结束标签时,就会调用这个方法。例如读到Books,Book,title等。那么对读到的标签进行判断后就可以进行存储操作啦!
- - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
- {
- }
这里标签参数就是elementName。
Step 5:对整个xml文件解析结束后的一些操作。
Step 6:这个暂不解释(我还没有用到)。
四、下面就是上代码的时候啦
.h文件
- #import <UIKit/UIKit.h>
- @class AppDelegate,Book;
- @interface ViewController : UIViewController <NSXMLParserDelegate> {
- NSMutableString *currentElementValue; //用于存储元素标签的值
- NSMutableArray *books; //用于存储一组书籍
- Book *aBook; //书籍实例,代表一本书
- BOOL storingFlag; //查询标签所对应的元素是否存在
- NSArray *elementToParse; //要存储的元素
- }
- - (IBAction)xmlButton:(id)sender;
- @end
说明:这里我用一个按键来触发xml解析。
.m文件
- #import "ViewController.h"
- #import "AppDelegate.h"
- @interface ViewController ()
- @end
- @implementation ViewController
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- // Do any additional setup after loading the view, typically from a nib.
- //初始化要解析的元素标签
- elementToParse = [[NSArray alloc] initWithObjects:@"title",@"author",@"summary", nil];
- }
- - (void)didReceiveMemoryWarning
- {
- [super didReceiveMemoryWarning];
- // Dispose of any resources that can be recreated.
- }
- - (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
- if([elementName isEqualToString:@"Books"]) {
- //Initialize the array.
- //在这里初始化用于存储最终解析结果的数组变量,我们是在当遇到Books根元素时才开始初始化
- books = [[NSMutableArray alloc] init];
- }
- else if([elementName isEqualToString:@"Book"]) {
- //Initialize the book.
- //当碰到Book元素时,初始化用于存储Book信息的实例对象aBook
- aBook = [[Book alloc] init];
- //Extract the attribute here.
- //从attributeDict字典中读取Book元素的属性
- aBook.bookID = [[attributeDict objectForKey:@"id"] integerValue];
- NSLog(@"ID:%i", aBook.bookID);
- }
- storingFlag = [elementToParse containsObject:elementName]; //判断是否存在要存储的对象
- }
- - (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
- // 当用于存储当前元素的值是空时,则先用值进行初始化赋值
- // 否则就直接追加信息
- if (storingFlag) {
- if (!currentElementValue) {
- currentElementValue = [[NSMutableString alloc] initWithString:string];
- }
- else {
- [currentElementValue appendString:string];
- }
- }
- }
- // 这里才是真正完成整个解析并保存数据的最终结果的地方
- - (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
- if ([elementName isEqualToString:@"Book"]) {
- [books addObject:aBook];
- aBook = nil;
- }
- if (storingFlag) {
- //去掉字符串的空格
- NSString *trimmedString = [currentElementValue stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
- //将字符串置空
- [currentElementValue setString:@""];
- if ([elementName isEqualToString:@"title"]) {
- aBook.title = trimmedString;
- NSLog(@"title :%@",aBook.title);
- }
- if ([elementName isEqualToString:@"author"]) {
- aBook.author = trimmedString;
- NSLog(@"author :%@",aBook.author);
- }
- if ([elementName isEqualToString:@"summary"]) {
- aBook.summary = trimmedString;
- NSLog(@"summary :%@",aBook.summary);
- }
- }
- }
- - (IBAction)xmlButton:(id)sender {
- //打开xml文件,读取数据到NSData
- NSString *path = [[NSBundle mainBundle] pathForResource:@"Books" ofType:@"xml"];
- NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path];
- NSData *data = [file readDataToEndOfFile];
- [file closeFile];
- //测试从xml接受到的数据
- NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- NSLog(@"%@",dataString);
- NSXMLParser *m_parser = [[NSXMLParser alloc] initWithData:data];
- //设置该类本身为代理类,即该类在声明时要实现NSXMLParserDelegate委托协议
- [m_parser setDelegate:self]; //设置代理为本地
- BOOL flag = [m_parser parse]; //开始解析
- if(flag) {
- NSLog(@"解析指定路径的xml文件成功");
- }
- else {
- NSLog(@"解析指定路径的xml文件失败");
- }
- }
- @end
iOS 详解NSXMLParser方法解析XML数据方法的更多相关文章
- iOS解析XML数据
iOS中解析XML数据的类是 NSXMLParser,详细使用方法如下: 假设现在在内存中有XML的二进制数据对象(NSData):data(该数据可能来自网络,也可能是本地的文件数据),设置NSX ...
- iOS学习笔记(九)——xml数据解析
在iPhone开发中,XML的解析有很多选择,iOS SDK提供了NSXMLParser和libxml2两个类库,另外还有很多第三方类库可选,例如TBXML.TouchXML.KissXML.Tiny ...
- iOS学习笔记(九)—— xml数据解析
在iPhone开发中,XML的解析有很多选择,iOS SDK提供了NSXMLParser和libxml2两个类库,另外还有很多第三方类库可选,例如TBXML.TouchXML.KissXML.Tiny ...
- 【iOS-cocos2d-X 游戏开发之九】Cocos2dx利用CCSAXParser解析xml数据&CCMutableDictionary使用与注意!
本站文章均为李华明Himi原创,转载务必在明显处注明:转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/iphone-cocos2dx/694.html ☞ ...
- IOS详解TableView——选项抽屉(天猫商品列表)
在之前的有篇文章讲述了利用HeaderView来写类似QQ好友列表的表视图. 这里写的天猫抽屉其实也可以用该方法实现,具体到细节每个人也有所不同.这里采用的是点击cell对cell进行运动处理以展开“ ...
- Android网络之数据解析----SAX方式解析XML数据
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- MySQL关闭过程详解和安全关闭MySQL的方法
MySQL关闭过程详解和安全关闭MySQL的方法 www.hongkevip.com 时间: -- : 阅读: 整理: 红客VIP 分享到: 红客VIP(http://www.hongkevip.co ...
- (四)SAX方式解析XML数据
SAX方式解析XML数据 文章来源:http://www.cnblogs.com/smyhvae/p/4044170.html 一.XML和Json数据的引入: 通常情况下,每个需要访问网络的应用程 ...
- 【Android Developers Training】 81. 解析XML数据
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
随机推荐
- VS2013与MySql建立连接;您的项目引用了最新实体框架;但是,找不到数据链接所需的与版本兼容的实体框架数据库 EF6使用Mysql的技巧
因为之前都是看别人的项目,而没有自己从头到尾建立一个项目,所以这次尝试搭建时就出现了问题,主要是ASP.Net MVC项目中VS2013和MySql的连接. 第一个问题: 数据库表已建好,相应的数据库 ...
- 173. Binary Search Tree Iterator
题目: Implement an iterator over a binary search tree (BST). Your iterator will be initialized with th ...
- 【一】 sched.h
第一个数据结构体是 task_struct ,这个数据结构被内核用来表示进程,包含其所有信息. 定义于文件 include/linux/sched.h 中,先看看其完整定义 struct task_s ...
- 【HDOJ】3473 Minimum Sum
划分树解.主席树解MLE. /* 3473 */ #include <iostream> #include <sstream> #include <string> ...
- Android开发之一些资源索引
1.android标题栏(titlebar)显示进度条 protected void onCreate(Bundle savedInstanceState) { super.onCreate(save ...
- Android开发:向下一个activity传递数据,返回数据给上一个activity
1.向下一个activity传递数据 activity1 Button button=(Button) findViewById(R.id.button1); button.setOnClickLis ...
- 1414. Astronomical Database(STL)
1414 破题 又逼着用stl 卡内存 trie树太耗了 水不过去 用set存字符串 set可以自己按一定顺序存 且没有重复的 再用lower_bound二分查找字符串的第一次出现 接着往后找就行了 ...
- js压缩、混淆和加密
最近看到有些论坛在讨论js压缩.混淆和加密的问题,特意找了些资料看了下,现在总结一下: 1.关于三者的定义与区别 压缩:删除 Javascript 代码中所有注释.跳格符号.换行符号及无用的空格,从而 ...
- poj 1328 Radar Installation(贪心)
题目:http://poj.org/problem?id=1328 题意:建立一个平面坐标,x轴上方是海洋,x轴下方是陆地.在海上有n个小岛,每个小岛看做一个点.然后在x轴上有雷达,雷达能覆盖的范 ...
- Windows如何安装自定义服务
系统:Windows8 开发环境:Visual Studio 2012 开发平台 .Net Framework 4.5 找到系统盘的 C:\Windows\Microsoft.NET\Framewor ...