前一篇文章已经介绍了如何通过URL从网络上获取xml数据。下面介绍如何将获取到的数据进行解析。

下面先看看xml的数据格式吧!

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Books>
  3. <Book id="1">
  4. <title>Circumference</title>
  5. <author>Nicholas Nicastro</author>
  6. <summary>Eratosthenes and the Ancient</summary>
  7. </Book>
  8. <Book id="2">
  9. <title>Copernicus Secret</title>
  10. <author>Jack Repcheck</author>
  11. <summary>How the scientific revolution began</summary>
  12. </Book>
  13. <Book id="3">
  14. <title>Angels and Demons</title>
  15. <author>Dan Brown</author>
  16. <summary>Robert Langdon is summoned to a Swiss</summary>
  17. </Book>
  18. </Books>

显然在这个xml中包括三本书的一些基本数据:id   title   author   summary  解析的过程就是将这些数据提取出来。

先简单介绍一下xml数据解析吧。xml数据的解析一般有两种方式:SAX(Simple API for XML)和DOM (Document Object Model),事件和文档。

dom实现的原理是把整个xml文档一次性读出,放在一个树型结构里。在需要的时候,查找特定节点,然后对节点进行读或写。他的主要优势是实现简单,读写平衡;缺点是比较占内存,因为他要把整个xml文档都读入内存,文件越大,这种缺点就越明显。
 

sax的实现方法和dom不同。他只在xml文档中查找特定条件的内容,并且只提取需要的内容。这样做占用内存小,灵活。

NSXMLParser 实现的是sax方法解析xml文件。

下面进入主题介绍如何对xml进行解析:

一、将上面的xml数据保存为Books.xml作为本地xml数据,并导入项目中。

二、由于book中含有几个属性,所以这里第一个book类。

Book.h文件:

  1. #import <Foundation/Foundation.h>
  2. @interface Book : NSObject
  3. @property (nonatomic, readwrite) NSInteger bookID;
  4. @property (nonatomic, retain) NSString  *title;
  5. @property (nonatomic, retain) NSString  *author;
  6. @property (nonatomic, retain) NSString  *summary;
  7. @end

Book.m文件

  1. #import "Book.h"
  2. @implementation Book
  3. @synthesize bookID;
  4. @synthesize title;
  5. @synthesize author;
  6. @synthesize summary;
  7. @end

三、要实现对xml数据的解析实际上是通过实现NSXMLParserDelegate委托中的几个方法。

  1. #pragma mark xmlparser
  2. //step 1 :准备解析
  3. - (void)parserDidStartDocument:(NSXMLParser *)parser
  4. {
  5. }
  6. //step 2:准备解析节点
  7. - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
  8. {
  9. }
  10. //step 3:获取首尾节点间内容
  11. - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
  12. {
  13. }
  14. //step 4 :解析完当前节点
  15. - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
  16. {
  17. }
  18. //step 5:解析结束
  19. - (void)parserDidEndDocument:(NSXMLParser *)parser
  20. {
  21. }
  22. //step 6:获取cdata块数据
  23. - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock
  24. {
  25. }

在实现xml解析过程以上方法中的step3 、4、5是必须的,而step1、5可选。

下面分别介绍:

Step 1: 在开始解析之前的一些准备工作,例如初始化一些存储变量。在我的这个例子中,使用了一个Book实例变量来存储一本书(也即是一组信息),一个可变数组来存储这三本书(即每一组信息都当成这个数组中的一个元素),(此次要注意理解数据变量之间的关系),其他变量就暂不介绍啦(待会看源代码就可以了)。

Step 2: 当解析器遇到xml的根标签和一组信息的开始标签时就开始调用这个方法,在这个xml文件中,遇到Books(xml文件的根标签),Book(一组信息的开始标签)时就会调用这个方法。那么也就可以知道这个方法在程序运行过程中被调用了多次。那么就可以用 if 语句判断遇到的是Books还是Book,然后做一些相应的操作(具体的话待会看源代码)。

  1. - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
  2. {
  3. }

注意其中的参数: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等。那么对读到的标签进行判断后就可以进行存储操作啦!

  1. - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
  2. {
  3. }

这里标签参数就是elementName。

Step 5:对整个xml文件解析结束后的一些操作。

Step 6:这个暂不解释(我还没有用到)。

四、下面就是上代码的时候啦

.h文件

  1. #import <UIKit/UIKit.h>
  2. @class AppDelegate,Book;
  3. @interface ViewController : UIViewController <NSXMLParserDelegate> {
  4. NSMutableString *currentElementValue;  //用于存储元素标签的值
  5. NSMutableArray *books;  //用于存储一组书籍
  6. Book *aBook;  //书籍实例,代表一本书
  7. BOOL storingFlag; //查询标签所对应的元素是否存在
  8. NSArray *elementToParse;  //要存储的元素
  9. }
  10. - (IBAction)xmlButton:(id)sender;
  11. @end

说明:这里我用一个按键来触发xml解析。

.m文件

    1. #import "ViewController.h"
    2. #import "AppDelegate.h"
    3. @interface ViewController ()
    4. @end
    5. @implementation ViewController
    6. - (void)viewDidLoad
    7. {
    8. [super viewDidLoad];
    9. // Do any additional setup after loading the view, typically from a nib.
    10. //初始化要解析的元素标签
    11. elementToParse = [[NSArray alloc] initWithObjects:@"title",@"author",@"summary", nil];
    12. }
    13. - (void)didReceiveMemoryWarning
    14. {
    15. [super didReceiveMemoryWarning];
    16. // Dispose of any resources that can be recreated.
    17. }
    18. - (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    19. if([elementName isEqualToString:@"Books"]) {
    20. //Initialize the array.
    21. //在这里初始化用于存储最终解析结果的数组变量,我们是在当遇到Books根元素时才开始初始化
    22. books = [[NSMutableArray alloc] init];
    23. }
    24. else if([elementName isEqualToString:@"Book"]) {
    25. //Initialize the book.
    26. //当碰到Book元素时,初始化用于存储Book信息的实例对象aBook
    27. aBook = [[Book alloc] init];
    28. //Extract the attribute here.
    29. //从attributeDict字典中读取Book元素的属性
    30. aBook.bookID = [[attributeDict objectForKey:@"id"] integerValue];
    31. NSLog(@"ID:%i", aBook.bookID);
    32. }
    33. storingFlag = [elementToParse containsObject:elementName];  //判断是否存在要存储的对象
    34. }
    35. - (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    36. // 当用于存储当前元素的值是空时,则先用值进行初始化赋值
    37. // 否则就直接追加信息
    38. if (storingFlag) {
    39. if (!currentElementValue) {
    40. currentElementValue = [[NSMutableString alloc] initWithString:string];
    41. }
    42. else {
    43. [currentElementValue appendString:string];
    44. }
    45. }
    46. }
    47. // 这里才是真正完成整个解析并保存数据的最终结果的地方
    48. - (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    49. if ([elementName isEqualToString:@"Book"]) {
    50. [books addObject:aBook];
    51. aBook = nil;
    52. }
    53. if (storingFlag) {
    54. //去掉字符串的空格
    55. NSString *trimmedString = [currentElementValue stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    56. //将字符串置空
    57. [currentElementValue setString:@""];
    58. if ([elementName isEqualToString:@"title"]) {
    59. aBook.title = trimmedString;
    60. NSLog(@"title :%@",aBook.title);
    61. }
    62. if ([elementName isEqualToString:@"author"]) {
    63. aBook.author = trimmedString;
    64. NSLog(@"author :%@",aBook.author);
    65. }
    66. if ([elementName isEqualToString:@"summary"]) {
    67. aBook.summary = trimmedString;
    68. NSLog(@"summary :%@",aBook.summary);
    69. }
    70. }
    71. }
    72. - (IBAction)xmlButton:(id)sender {
    73. //打开xml文件,读取数据到NSData
    74. NSString *path = [[NSBundle mainBundle] pathForResource:@"Books" ofType:@"xml"];
    75. NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path];
    76. NSData *data = [file readDataToEndOfFile];
    77. [file closeFile];
    78. //测试从xml接受到的数据
    79. NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    80. NSLog(@"%@",dataString);
    81. NSXMLParser *m_parser = [[NSXMLParser alloc] initWithData:data];
    82. //设置该类本身为代理类,即该类在声明时要实现NSXMLParserDelegate委托协议
    83. [m_parser setDelegate:self];  //设置代理为本地
    84. BOOL flag = [m_parser parse]; //开始解析
    85. if(flag) {
    86. NSLog(@"解析指定路径的xml文件成功");
    87. }
    88. else {
    89. NSLog(@"解析指定路径的xml文件失败");
    90. }
    91. }
    92. @end

iOS 详解NSXMLParser方法解析XML数据方法的更多相关文章

  1. iOS解析XML数据

    iOS中解析XML数据的类是  NSXMLParser,详细使用方法如下: 假设现在在内存中有XML的二进制数据对象(NSData):data(该数据可能来自网络,也可能是本地的文件数据),设置NSX ...

  2. iOS学习笔记(九)——xml数据解析

    在iPhone开发中,XML的解析有很多选择,iOS SDK提供了NSXMLParser和libxml2两个类库,另外还有很多第三方类库可选,例如TBXML.TouchXML.KissXML.Tiny ...

  3. iOS学习笔记(九)—— xml数据解析

    在iPhone开发中,XML的解析有很多选择,iOS SDK提供了NSXMLParser和libxml2两个类库,另外还有很多第三方类库可选,例如TBXML.TouchXML.KissXML.Tiny ...

  4. 【iOS-cocos2d-X 游戏开发之九】Cocos2dx利用CCSAXParser解析xml数据&CCMutableDictionary使用与注意!

    本站文章均为李华明Himi原创,转载务必在明显处注明:转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/iphone-cocos2dx/694.html ☞ ...

  5. IOS详解TableView——选项抽屉(天猫商品列表)

    在之前的有篇文章讲述了利用HeaderView来写类似QQ好友列表的表视图. 这里写的天猫抽屉其实也可以用该方法实现,具体到细节每个人也有所不同.这里采用的是点击cell对cell进行运动处理以展开“ ...

  6. Android网络之数据解析----SAX方式解析XML数据

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  7. MySQL关闭过程详解和安全关闭MySQL的方法

    MySQL关闭过程详解和安全关闭MySQL的方法 www.hongkevip.com 时间: -- : 阅读: 整理: 红客VIP 分享到: 红客VIP(http://www.hongkevip.co ...

  8. (四)SAX方式解析XML数据

    SAX方式解析XML数据 ​文章来源:http://www.cnblogs.com/smyhvae/p/4044170.html 一.XML和Json数据的引入: 通常情况下,每个需要访问网络的应用程 ...

  9. 【Android Developers Training】 81. 解析XML数据

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

随机推荐

  1. thinkphp 定制错误页面

    在前台配置文件里加上: 'TMPL_EXCEPTION_FILE' => '.Public/tpl/error.html',// 异常cuowu页面的模板文件 然后在Public下新建一个tpl ...

  2. 双机高可用、负载均衡、MySQL(读写分离、主从自动切换)架构设计

    前几天网友来信说帮忙实现这样一个架构:只有两台机器,需要实现其中一台死机之后另一台能接管这台机器的服务,并且在两台机器正常服务时,两台机器都能用上.于是设计了如下的架构. 架构简介 此架构主要是由ke ...

  3. MyBatis的两个配置文件

    MyBatis有两个基本的配置文件,一个用来配置环境信息(mybatis.xml),一个用来写SQL语句(xxMapper.xml). mybatis.xml: <?xml version=&q ...

  4. Kali2.0 Sqlmap清除历史扫描日志

    使用Sqlmap扫描SQL注入漏洞时,首次扫描会在SQL的/root/.sqlmap/output/目录下留下 以IP地址为名称的文件夹,如下所示: 而如果该安全漏洞经过修复后,再次使用SQLMAP扫 ...

  5. xml--通过jdom解析及生产XML

    JDOM是一种使用 XML 的独特 Java 工具包,用于快速开发 XML 应用程序.它的设计包含 Java 语言的语法乃至语义. JAXP (用于 XML 语法分析的 Java API)包含了三个软 ...

  6. DSPLIB for C6455+CCSv3.3

    问题描述: Hello everybody, I was looking for DSPLIB libraries optimized for C6455 processors. I found th ...

  7. 【HDOJ】1667 The Rotation Game

    1. 题目描述有个#字型的条带,可以从横线或竖线进行循环移动,求通过各种移动最终使中心的8个字符全等的长度最短并相同长度字典序最小的操作序列.2. 基本思路24个数据,8种移动方式,数据量很小了,所以 ...

  8. poj1925Spiderman(dp)

    链接 确实是破题 按复杂度估计怎么着也不能按坐标D 啊 网上的代码交上去还TLE 无语了  多次TLE之后终于看到一次WA..好高兴 以横坐标进行DP dp[j] = min(dp[j],dp[2*x ...

  9. c++ 头文件 及 sort

    c++  sort :http://www.16kan.com/post/997260.html http://wenku.baidu.com/view/e064166daf1ffc4ffe47ac6 ...

  10. UVa 540 (团体队列) Team Queue

    题意: 每个人都属于一个团体,在排队的时候,如果他所在的团体有人在队伍中,则他会站到这个团体的最后.否则站到整个队伍的队尾. 输出每次出队的人的编号. 分析: 容易看出,长队中,在同一个团体的人是排在 ...