IOS开发指南学习——XML解析

本文介绍iOS开发中使用NSXML及TBXML框架解析XML文件的方法。NSXML基于SAX模式,适用于大型文件;TBXML基于DOM模式,易于操作。文章详细展示了代码实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们知道xml是一种数据交换格式,在各种语言中的使用都非常广泛。

在学习java的过程中我已经对xml解析有了一定的了解,在java中对xml文档进行解析也是一件比较麻烦复杂的事情,当时对我也造成了不下的阻力。

在这几天学习ios网络编程的时候,我又遇到了xml解析的问题。

在ios开发中,iOS SDK提供了NSXML和libxml2两种xml框架,另外还有许多诸如TBXML、touchXML等的第三方框架可以使用。

一、使用NSXML框架

在学习中我主要使用了NSXML和TBXML两种框架进行xml解析,其中NSXML是使用了SAX的解析模式,这是一种基于事件驱动的解析模式,简单来说就是从上到下扫描整个xml文档,每当遇到开始标签、结束标签以及属性时,就会触发相应的事件。

基于代码复用性的考虑,我们编写一个专门的xml解析类用来使用NSXML框架进行xml解析:

#import <Foundation/Foundation.h>

@interface NotesXMLParser : NSObject<NSXMLParserDelegate>

@property (strong,nonatomic) NSMutableArray* notes;
@property (strong,nonatomic) NSString* currentTagName;

- (void)start;

@end

<pre name="code" class="objc">#import "NotesXMLParser.h"

@implementation NotesXMLParser

@synthesize notes = _notes;
@synthesize currentTagName = _currentTagName;

- (void)start{
    //设置xml文件路径
    NSString* path = [[NSBundle mainBundle] pathForResource:@"Notes" ofType:@"xml"];
    NSURL* url = [NSURL fileURLWithPath:path];
    
    //开始解析xml
    NSXMLParser* parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
    parser.delegate = self;
    [parser parse];
}

//在开始解析xml文档时调用,可用来初始化变量
- (void)parserDidStartDocument:(NSXMLParser *)parser{
    _notes = [NSMutableArray new];
}

//解析出错时调用
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
    NSLog(@"%@",parseError);
}

//遇到开始标签时调用
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
    //记录当前解析的标签名
    _currentTagName = elementName;
    //若是Note标签,则要新建一个字典类型加入到notes中
    if ([_currentTagName isEqualToString:@"Note"]) {
        NSString* _id = [attributeDict objectForKey:@"id"];
        NSMutableDictionary* dict = [NSMutableDictionary new];
        [dict setObject:_id forKey:@"id"];
        [_notes addObject:dict];
    }
}

//遇到字符串时调用
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    //替换空格和回车
    string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    //遇到空字符串则跳过
    if ([string isEqualToString:@""]) {
        return;
    }
    //取出当前解析中的字典类型
    NSMutableDictionary* dict = [_notes lastObject];
    //当字符创非空,添加到字典类型中
    if ([_currentTagName isEqualToString:@"CDate"] && dict) {
        [dict setObject:string forKey:@"CDate"];
    }
    if ([_currentTagName isEqualToString:@"Content"] && dict) {
        [dict setObject:string forKey:@"Content"];
    }
    if ([_currentTagName isEqualToString:@"UserID"] && dict) {
        [dict setObject:string forKey:@"UserID"];
    }
}

//遇到结束标签
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    _currentTagName = nil;
}

//xml文档解析完毕
- (void)parserDidEndDocument:(NSXMLParser *)parser{
    //通过通知机制将解析的结果传送回调用处
    [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadViewNotification" object:self.notes userInfo:nil];
    self.notes = nil;
}

@end




然后,在需要进行xml解析的地方实例化该xml解析类并进行xml解析,在本例中,我们是在试图控制器中的ViewDidLoad方法中进行xml解析的:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    //注册通知接受者
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadView:) name:@"reloadViewNotification" object:nil];
    //实例化xml解析类并进行解析
    NotesXMLParser* parser = [NotesXMLParser new];
    [parser start];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

//接收到通知后调用的方法
- (void)reloadView:(NSNotification*)notification{
    self.listData = [notification object];
    [self.tableView reloadData];
}

到此就完成了使用NSXML进行xml解析的全过程,可以发现使用NSXML进行解析会比较复杂,我们需要手动写解析的全过程。

二、使用TBXML框架

TBXML进行xml解析是基于DOM模式的解析,DOM模式会将xml文件的元素当做一个树状结构,一次性读入内存中。由于TBXML是第三方框架,所以不能直接使用,使用的过程如下。

1.首先到https://github.com/71squared/TBXML 下载TBXML框架,解压后将TBXML-Headers和TBXML-Code文件夹添加到工程中:

       

2.在工程中添加TBXML所依赖的Framework和库,如下图:


3.添加预编译头文件,点击File-->New-->File...菜单项,选择iOS-->Other-->PCH File 文件,创建预编译头文件PrefixHeader.pch,并编写如下:

#ifndef TBXML_PrefixHeader_pch
#define TBXML_PrefixHeader_pch

#import <Foundation/Foundation.h>
#define ARC_ENABLED

// Include any system framework and library headers here that should be included in all compilation units.
// You will also need to set the Prefix Header build setting of one or more of your targets to reference this file.

#endif

4.配置预编译头文件到工程,打开工程,选择TARGETS-->工程名-->Build Settings-->Apple LLVM 6.1-Language-->Prefix Header 输入PrefixHeader.pch,如下图:



5.到这里,就已经将TBXML框架加入到工程之中了,接下来,只需要修改xml解析类中的start方法,就可以了,并不需要修改其他的代码:

- (void)start{
    //初始化notes变量
    _notes = [NSMutableArray new];
    //设置xml文件路径
    TBXML* tbxml = [[TBXML alloc] initWithXMLFile:@"Notes.xml" error:nil];
    //设置根节点
    TBXMLElement* root = tbxml.rootXMLElement;
    
    if (root) {
        //在根节点的子节点中寻找Note标签的节点
        TBXMLElement* noteElement = [TBXML childElementNamed:@"Note" parentElement:root];
        
        while (noteElement != nil) {
            //解析各属性
            NSMutableDictionary* dict = [NSMutableDictionary new];
            //添加id属性并添加到notes中
            [dict setObject:[TBXML valueOfAttributeNamed:@"id" forElement:noteElement error:nil] forKey:@"id"];
            [_notes addObject:dict];
            
            //添加Note节点中的各个子节点到字典类型中
            TBXMLElement* CDateElement =  [TBXML childElementNamed:@"CDate" parentElement:noteElement];
            if (CDateElement != nil) {
                [dict setObject:[TBXML textForElement:CDateElement] forKey:@"CDate"];
            }
            
            TBXMLElement* ContentElement = [TBXML childElementNamed:@"Content" parentElement:noteElement];
            if (ContentElement != nil) {
                [dict setObject:[TBXML textForElement:ContentElement] forKey:@"Content"];
            }
            
            TBXMLElement* UserIDElement = [TBXML childElementNamed:@"UserID" parentElement:noteElement];
            if (UserIDElement != nil) {
                [dict setObject:[TBXML textForElement:UserIDElement] forKey:@"UserID"];
            }
            
            //寻找与note节点出于同一级的下一个Note节点
            noteElement = [TBXML nextSiblingNamed:@"Note" searchFromElement:noteElement];
        }
        NSLog(@"完成TBXML解析");
        
        //通过通知机制传输解析结果
        [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadViewNotification" object:self.notes userInfo:nil];
        self.notes = nil;
    }
}

可以看出,使用了tbxml框架来进行解析,不仅代码量减少了很多,解析的过程也更加地清晰,使用起来更加简单。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值