在iOS平台上可用的XML解析方法有很多,如KissXML、Jason等,最近一直在研究,网上可以找到的NSXMLParser Demo很少,大多数代码十分复杂,下面是使用苹果提供的NSXMLParser来解析XML的一种方法。适合初学者学习。
例:XML文件如下
<?xml version="1.0" encoding="UTF-8"?> <response> <responseCode>0</responseCode> <rows> <row> <bookImage>mingchaomeiyoushi.png</bookImage> <bookTitle>明朝没有事</bookTitle> <bookAuthor>Xong</bookAuthor> <bookBroadcaster>哈哈</bookBroadcaster> <bookPrice>$0.99</bookPrice> </row> <row> <bookImage>qiyejia.png</bookImage> <bookTitle>苹果</bookTitle> <bookAuthor>Apple</bookAuthor> <bookBroadcaster>乔布斯</bookBroadcaster> <bookPrice>$5.99</bookPrice> </row> </rows> </response>
首先介绍一下NSXMLParser这个类,这个类的实例以事件驱动的方式来解析XML,在XML文件中,一旦遇到元素、属性、CDATA块和注释等等就通知通知它的delegate。NSXMLParser只是通知它的delegate去做这些事,本身并不解析XML,所以我们在解析XML的时候,就要用到NSXMLParserDelegate这个protocol。这个protocol中包括很多方法,介绍常用的几个:
– parser:didStartElement:namespaceURI:qualifiedName:attributes:
当碰到元素头的时候调用该方法,如当遇到<response>时方法调用
– parser:didEndElement:namespaceURI:qualifiedName:
– parser:foundCharacters:
有了这三个方法,我们就可以轻松的解析出上述XML文件了,首先我们定义一个名为XMLParser的类
#import <Foundation/Foundation.h> @class Book; @interface XMLParser : NSObject <NSXMLParserDelegate> { NSString *responseCode; NSMutableArray *books; NSMutableArray *currentString; Book *currentBook; } @property (nonatomic, retain) NSMutableArray *books; @property (nonatomic, retain) NSString *responseCode; @property (nonatomic, retain) NSMutableArray *currentString; @property (nonatomic, retain) Book *currentBook; - (void)addBooks:(Book *)objects; //开始解析 - (void)startParser:(NSData *)xmlData error:(NSError **)err; @end
- (void)startParser:(NSData *)xmlData error:(NSError **)err { NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:xmlData] autorelease]; [parser setDelegate:self]; [parser setShouldProcessNamespaces:NO]; [parser setShouldReportNamespacePrefixes:NO]; [parser setShouldResolveExternalEntities:NO]; currentString = [NSMutableArray array]; books = [NSMutableArray array]; //通知delegate解析XML [parser parse]; NSLog(@"responseCode = %@",responseCode); NSLog(@"books = %@",books); }
首先实例化NSXMLParser类,用这个类来发送通知,然后开始解析,首先在XML文件中遇到<response>调用- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { [currentString removeAllObjects]; }
然后,如上所述- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { if (![string isEqualToString:@""]) [self.currentString addObject:string]; }
调用,我们可以将读到的string保存在一个全局变量currentString中来给我们的model赋值,在<response>中并无字符元素,所以string为空,当我们遇到<responseCode>时,string的值就变为0了,当我们遇到</responseCode>时- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { if (currentBook == nil) { currentBook = [[Book alloc] init]; } if([elementName isEqualToString:@"responseCode"]) { self.responseCode = [self.currentString lastObject]; }else if([elementName isEqualToString:@"bookImage"]){ self.currentBook.bookImage = [self.currentString lastObject]; }else if([elementName isEqualToString:@"bookTitle"]){ self.currentBook.bookTitle = [self.currentString lastObject]; }else if([elementName isEqualToString:@"bookAuthor"]){ self.currentBook.bookAuthor = [self.currentString lastObject]; }else if([elementName isEqualToString:@"bookBroadcaster"]){ self.currentBook.bookBroadcaster = [self.currentString lastObject]; }else if([elementName isEqualToString:@"bookPrice"]){ self.currentBook.bookPrice = [self.currentString lastObject]; }else if([elementName isEqualToString:@"row"]){ [self addBooks:self.currentBook]; [self setCurrentBook:nil]; } }
该方法调用,我们就可以从前面方法中获取到的currentString来保存XML中元素的值。这三个方法循环调用,直到XML文件全部解析完毕。
完整代码地址如下:点击打开链接以前的代码写的比较混乱,很多人说下下来要么运行不了,要么有各种问题,重新写了一个Demo,希望对大家有帮助,上面的连接地址作废
新的代码地址如下:点击打开链接
个人理解能力有限,欢迎大家指正