分享

IOS开发系列之xml解析阿堂教程(1)

 叹落花 2014-12-20
             过ios开发的朋友都知道,目前在ios开发中,和服务端交互时,主要是使用xml和json两种解析方式。今天阿堂介绍的是xml的解析方式的实例,对于json解析方式,我会在后面继续分享。
         下面,阿堂对于xml的解析框架,首先先做个简单介绍。
         ios sdk 提供了两个xml框架。
         1)nsxml:它是基于objective-c语言的sax解析框架,是ios sdk默认的xml解析框架,不支持dom模式。
         2)libxml2: 它是基于c语言的xml解析器,被苹果整合在ios sdk中,支持sax和dom模式。

        第三方xml解析框架
        1)tbxml:它是轻量级的dom模式解析库,不支持xml文档验证和xpath,只能读取xml文档,不能写xml文档,但是解析xml是最快的。
        2)touchxml:它是基于dom模式的解析库,与 tbxml类似,只能读取xml文档,不能写xml文档。
        3)kissxml:它是基于dom模式的解析库,基于touchxml,主要的不同是可以写入xml文档。
        4)tinyxml:它是基于c++语言模式解析库,可以读写xml文档,不支持xpath.
        5)gdataxml:它是基于dom模式的解析库,由google开发,可以读写xml文档,支持xpath查询。

     从性能上来看,nsxml和tbxml比较优秀,所以阿堂就主要介绍这两个xml解析器了

      一. nsxml解析实例demo

    1.  Notes.xml
 IOS开发系列之xml解析阿堂教程(1)




    2.使用nsxml

   nsxml是ios sdk自带的,也是苹果默认的解析框架,它采用sax模式解析,是sax解析模式的代表。nsxml框架的核心是nsxmlparser和它的委托协议nsxmlparserdelegate,其中主要的解析工作是在nsxmlparserdelegate实现类中完成的。委托中定义了很多回调方法,在sax解析器从上到下遍历xml文档的过程中,遇到开始标签,结束标签,文档开始和字符串时就会触发这些方法。这些方法比较多,下面我们列出几个常用的方法

--parserDidStartDocument:
--parser:didStartElement:namespaceURI:qualifiedName:attributes:
--parser:foundCharacters:
--parser:didEndElement:namespaceURI:qualifiedName:
--parserDidEndDocument:


专门的解析类
NotesXMLParser.h,  NotesXMLParser.m

NotesXMLParser.h
#import

@interface NotesXMLParser : NSObject

//解析出的数据内部是字典类型
@property (strong,nonatomic) NSMutableArray *notes;
//当前标签的名字
@property (strong,nonatomic) NSString *currentTagName;

//开始解析
-(void)start;

@end

NotesXMLParser.m

#import "NotesXMLParser.h"

@implementation NotesXMLParser


-(void)start
{
    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];
    NSLog(@"解析完成...");
}

//文档开始的时候触发
- (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 *)qualifiedName
    attributes:(NSDictionary *)attributeDict
{
    _currentTagName = elementName;
   
    NSLog(@"_currentTagName = %@",_currentTagName);
   
    if ([_currentTagName isEqualToString:@"Note"]) {
        NSString *_id = [attributeDict objectForKey:@"id"];
        NSLog(@"note对应的属性id = %@",_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 compare:@""] == NSOrderedDescending) {
        NSLog(@"字符串 = %@",string);
    }
   
   
    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;
{
    self.currentTagName = nil;
}


//遇到文档结束时候触发
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadViewNotification" object:self.notes userInfo:nil];
    self.notes = nil;
}

@end


3.主要调用类



MasterViewController.h

#import


@class DetailViewController;

@interface MasterViewController : UITableViewController

@property (strong, nonatomic) DetailViewController *detailViewController;
//保存数据列表
@property (nonatomic,strong) NSMutableArray* listData;


@end


MasterViewController.m

#import "MasterViewController.h"
#import "DetailViewController.h"
#import "NotesXMLParser.h"
#import "NotesTBXMLParser.h"


@implementation MasterViewController

- (void)awakeFromNib
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        self.clearsSelectionOnViewWillAppear = NO;
        self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
    }
    [super awakeFromNib];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.navigationItem.leftBarButtonItem = self.editButtonItem;
   
    self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
   
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(reloadView:)
                                                 name:@"reloadViewNotification"
                                               object:nil];
   
    NotesXMLParser *parser = [NotesXMLParser new];
//    NotesTBXMLParser *parser = [NotesTBXMLParser new];
    //开始解析
    [parser start];

}

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


#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.listData.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"  forIndexPath:indexPath];
 
    NSMutableDictionary*  dict = self.listData[indexPath.row];
    cell.textLabel.text = [dict objectForKey:@"Content"];
    cell.detailTextLabel.text = [dict objectForKey:@"CDate"];
   
    return cell;
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the specified item to be editable.
    return YES;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
       
//        Note *note = [self.listData objectAtIndex:[indexPath row]];       
//        NoteBL *bl = [[NoteBL alloc] init];
//        self.listData = [bl remove: note];
       
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
       
    } else if (editingStyle == UITableViewCellEditingStyleInsert) {
       
    }
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
//        Note  *note = self.listData[indexPath.row];
//        self.detailViewController.detailItem = note;
    }
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"showDetail"]) {
//       NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
//        Note  *note = self.listData[indexPath.row];
//        [[segue destinationViewController] setDetailItem:note];
    }
}

#pragma mark - 处理通知
-(void)reloadView:(NSNotification*)notification
{
    NSMutableArray *resList = [notification object];
    self.listData  = resList;
    [self.tableView reloadData];
}


@end


4.运行结果
IOS开发系列之xml解析阿堂教程(1)

IOS开发系列之xml解析阿堂教程(1)

IOS开发系列之xml解析阿堂教程(1)

  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多