抽空讲一下以前做的xml解析,自己的工作先扔一边吧!
先看看要解析的数据格式
<?xml version='1.0' encoding='UTF-8'?> <chats> <chat> <speaker><![CDATA[self]]></speaker> <text><![CDATA[hello]]></text> </chat> <chat> <speaker><![CDATA[other]]></speaker> <text><![CDATA[world]]></text> </chat> <chat> <speaker><![CDATA[other1]]></speaker> <text><![CDATA[world1]]></text> </chat> <chat> <speaker><![CDATA[other1]]></speaker> <text><![CDATA[world1]]></text> </chat> <chat> <speaker><![CDATA[other2]]></speaker> <text><![CDATA[world2]]></text> </chat> <chat> <speaker><![CDATA[other3]]></speaker> <text><![CDATA[world3]]></text> </chat> <chat> <speaker><![CDATA[other4]]></speaker> <text><![CDATA[world4]]></text> </chat> <chat> <speaker><![CDATA[other5]]></speaker> <text><![CDATA[world5]]></text> </chat> </chats>
把它放在了一个叫chatLog.xml的文件中,再拖到工程里面来
这个解析只需要一个类就够了,下面来看看头文件
#import <UIKit/UIKit.h> @interface xmlParseViewController : UIViewController<NSXMLParserDelegate> {//注意要添加代理!!! NSMutableArray *chatArray; NSString *chatFile; NSMutableDictionary *currentChatInfo; NSMutableString *currentString; BOOL storingCharacters; IBOutlet UITableView *table; } @end
下面来看看.m文件
#import "xmlParseViewController.h" @implementation xmlParseViewController static NSString *kName_Chats = @"chats"; static NSString *kName_Chat = @"chat"; static NSString *kName_Speaker = @"speaker"; static NSString *kName_Text = @"text"; - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *) qualifiedName attributes:(NSDictionary *)attributeDict { if ([elementName isEqualToString:kName_Chats]) { [chatArray removeAllObjects];//开始之前先将数组元素移除 } else if ([elementName isEqualToString:kName_Chat]) { [currentChatInfo removeAllObjects];//字典元素也要移除 } else if ([elementName isEqualToString:kName_Speaker] || [elementName isEqualToString:kName_Text]) { [currentString setString:@""];//将数组也置为空,注意写法 storingCharacters = YES;//此处开始解析 } } - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { if ([elementName isEqualToString:kName_Chats]) { //这里什么也不做 } else if ([elementName isEqualToString:kName_Chat]) { [chatArray addObject:[NSDictionary dictionaryWithDictionary:currentChatInfo]]; //把字典添加进数组 } else if ([elementName isEqualToString:kName_Speaker] || [elementName isEqualToString:kName_Text]) { [currentChatInfo setObject:[NSString stringWithString:currentString] forKey:elementName]; //把字符串添加进字典 } storingCharacters = NO;//关闭解析 } - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { if (storingCharacters) [currentString appendString:string]; //把解析出来的字符串添加到实例变量字符串 } - (void)viewDidLoad { [super viewDidLoad]; NSString *path=[[NSBundle mainBundle] pathForResource:@"chatLog" ofType:@"xml"]; currentString = [[NSMutableString alloc] initWithCapacity:0]; currentChatInfo = [[NSMutableDictionary alloc] initWithCapacity:2]; chatArray = [[NSMutableArray alloc] initWithCapacity:0]; [NSThread detachNewThreadSelector:@selector(loadThread:) toTarget:self withObject:path];//在这里新开了一个线程去加载文件,一般加载文件或下载都采用多线程的方式 } - (void) finshLoadFile { UITableView *tableView = (UITableView *)table; [tableView reloadData]; } - (void) loadThread:(NSString *)xmlFile { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSXMLParser *chatLogParser = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL fileURLWithPath:xmlFile]]; [chatLogParser setDelegate:self];//千万别忘了设置代理 [currentString setString:@""]; [currentChatInfo removeAllObjects]; [chatLogParser parse]; [chatLogParser release]; [self performSelectorOnMainThread:@selector(finshLoadFile) withObject:nil waitUntilDone:YES]; [pool release]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [chatArray count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease]; cell.backgroundColor = [UIColor colorWithRed:0.859f green:0.886f blue:0.929f alpha:1.0f]; cell.selectionStyle = UITableViewCellSelectionStyleNone; } NSDictionary *chatInfo = [chatArray objectAtIndex:[indexPath row]]; cell.textLabel.text = [chatInfo objectForKey:@"text"]; cell.detailTextLabel.text = [chatInfo objectForKey:@"speaker"]; return cell; } - (void)dealloc { [currentString release]; [currentChatInfo release]; [chatArray release]; [super dealloc]; } @end
说明一下,其实解析用到的函数只有三个,分别是
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *) qualifiedName attributes:(NSDictionary *)attributeDict;
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;
他们的作用分别是开始解析元素,结束解析元素和得到元素。
至于具体的解析步骤在代码中有说明,一般都是按照这几个步骤来的。
在ViewDidLoad中,[NSThread detachNewThreadSelector:@selector(loadThread:) toTarget:self withObject:path];
开启一个线程去调用loadThread:方法,而在loadThread中初始化一个NSXMLParser的对象开始解析。
[self performSelectorOnMainThread:@selector(finshLoadFile) withObject:nil waitUntilDone:YES]这个方法是更新主线程的界面的方法,因为在子线程内无法更新主线程的视图(规定),所以要在子线程中调用这个方法去更新主线程的界面。
之后加载到表格的方法就不用多说了吧很简单,这个框架也适合做在子线程里下载图片等等工作,更换loadThread方法就行了。
有问题积极留言啊,我不厌其烦地为大家解决!