xml多线程解析,简单易懂的例子

 

抽空讲一下以前做的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方法就行了。
有问题积极留言啊,我不厌其烦地为大家解决!
 
原文地址:https://www.cnblogs.com/xiaobaizhu/p/2790048.html