ios XML解析

       我们知道,ios XML解析一共有两种方法,一种是SAX解析,另一种是DOM解析。两者之间的区别就是 SAX是打印式解析,也就是我们常说的逐行解析。DOM是复印式解析,也就是我们常说的整篇解析。如果在解析过程中遇到错误,SAX解析会停止到出现错误的前一行,而DOM解析不会解析出任何的数据。但是因为SAX解析的缺点是逐行解析,所以相对于DOM解析来说速度比较慢。

       下面我们通过一个例子具体来看一下两种解析方式:


        首先,我们来具体实现SAX方法:

        1.先建立一个方法,通过此方法找到所要解析的文件路径,建立NSXMLParser对象,通过parser对象来设置代理,并调用parse方法来进行解析

- (void)startParser{
    NSString *path = [[NSBundle mainBundle]pathForResource:@"citys" ofType:@"xml"];
    NSData *filedata = [NSData dataWithContentsOfFile:path];
    NSXMLParser *parser = [[NSXMLParser alloc]initWithData:filedata];
    [parser setDelegate:self];
    [parser parse];  //调用方法进行解析
}
再在.h文件中声明NSXMLParser协议:

<NSXMLParserDelegate>

2.SAX解析中,解析数据时会走两种方法,分别是:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict;
        和

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;
        这里的参数大家可以自行打印nslog进行测试,这里不便多说。

在我们这个需要解析的文件中,所需要的数据都是每一个元素的属性,所以我们不用didEndElement这个方法,只用到第一个方法,通过方法的最后一个对象attributeDict来找到我们需要的属性来进行调用。在这之前,我们需要定义一个NSMutableArray类型的数组并初始化和释放。建立完成后,开始进行第一个方法的实现:

static NSString *kCity = @"city";
static NSString *kCityname = @"name";
static NSString *klat  = @"latitude_e6";
static NSString *klon  = @"longitude_e6";//声明常量串

 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
    if ([elementName isEqualToString:kCity]) {
        SaxModel *model = [[DomModel alloc]init];//这里需要自定义model类
        [_tablearray addObject:model];           //将model添加到刚才定义的可变数组中
        [model release];
    }if ([elementName isEqualToString:kCityname]) {       

        SaxModel *model = [_tablearray lastObject];
        NSString *str = [attributeDict objectForKey:@"data"]; //将属性中的城市名取出
        model.cityname = str;                                 //将取出的属性赋值给model中对应的成员
    }if ([elementName isEqualToString:klat]) {
        SaxModel *model = [_tablearray lastObject];
        NSString *str = [attributeDict objectForKey:@"data"];
        model.Jcity = str;
    }if ([elementName isEqualToString:klon]) {
        SaxModel *model = [_tablearray lastObject];
        NSString *str = [attributeDict objectForKey:@"data"];
        model.Wcity = str;
    }
}

此时,数据已经全部解析完毕保存在model中,我们将每一个model存储在可变数组—tablearray中,方便调用。我们就可以在一个视图控制器建立tableview,通过tableview的cell来检验我们解析的数据是否正确。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return _tablearray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *cellinentify = @"cell";
    DIYCell *cell = [tableView dequeueReusableCellWithIdentifier:cellinentify];
    if (!cell) {
        cell = [[[DIYCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellinentify] autorelease];
    }
    SaxModel *model = [_tablearray objectAtIndex:indexPath.row];
    [cell.cityname setText:model.cityname];
    [cell.Jcitylabel setText:model.Jcity];
    [cell.Wcitylabel setText:model.Wcity];
    return cell;
}

这里的cell是我自定义的,.h文件如下:


#import <UIKit/UIKit.h>

@interface DIYCell : UITableViewCell

@property (retain,nonatomic) UILabel *cityname;  //城市名
@property (retain,nonatomic) UILabel *Jcitylabel;//城市经度
@property (retain,nonatomic) UILabel *Wcitylabel;//城市纬度

@end
cell的.m 文件:

#import "DIYCell.h"
@implementation DIYCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
        _cityname = [[UILabel alloc]initWithFrame:CGRectZero];
        _Jcitylabel = [[UILabel alloc]initWithFrame:CGRectZero];
        _Wcitylabel = [[UILabel alloc]initWithFrame:CGRectZero];
        
        [self.contentView addSubview:_cityname];
        [self.contentView addSubview:_Jcitylabel];
        [self.contentView addSubview:_Wcitylabel];
    }
    return self;
}

 - (void)layoutSubviews{
    [_cityname setFrame:CGRectMake(5, 5, 60, 30)];
    [_Jcitylabel setFrame:CGRectMake(70, 5, 80, 30)];
    [_Wcitylabel setFrame:CGRectMake(155, 5, 100, 30)];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end

最后输出结果:


2.我们再来具体实现DOM 方法:


1.在解析之前,我们需要先使用两个文件:




如果有需要的可以留言。DOM解析文件。


下面讲解一下适配这两个文件:

在build Settings查找Header Search Paths,双击,并点击添加:


然后输入:/usr/include/libxml2,点击回车。



再查找other Linker Flags,点击添加-lxml2

配置完成。


然后进行解析:(建议与数据图配合理解,比较容易,注意层级关系)


- (void)DomParserAttribute{
    //与Sax解析一样,先找到需要解析的文件路径,再解析
    NSString *path = [[NSBundle mainBundle]pathForResource:@"citys" ofType:@"xml"];
    NSData *filedata = [NSData dataWithContentsOfFile:path];
    NSError *error = Nil;
    GDataXMLDocument *document = [[GDataXMLDocument alloc]initWithData:filedata options:GDataXMLDocumentKind error:&error];
    if (error) {
        NSLog(@"error = %@",error);
    }
    GDataXMLElement *root = [document rootElement];//找到根节点
    NSArray *arr = [root children];//这里注意,根节点的子节点是以数组形式存在
    GDataXMLElement *cityselement = [arr lastObject];
    NSArray *cityarray = [cityselement children];
    for (GDataXMLElement *element in cityarray) {
        DomModel *model = [[DomModel alloc]init];
        [_tablearray addObject:model];//同样与Sax解析一样,将model放入数组中
        NSArray *desription = [element children];
        for (GDataXMLElement *value in desription) {
            model = [_tablearray lastObject];
            if ([value.name isEqualToString:@"name"]) {
                GDataXMLNode *node = [value attributeForName:@"data"];//取出每一个元素的属性值
                model.cityname = [node stringValue];
            }
            if ([value.name isEqualToString:@"latitude_e6"]) {
                GDataXMLNode *node = [value attributeForName:@"data"];
                model.Jcity = [node stringValue];
            }
            if ([value.name isEqualToString:@"longitude_e6"]) {
                GDataXMLNode *node = [value attributeForName:@"data"];
                model.Wcity = [node stringValue];
            }
        }
    }
    
}

这里,我们已经将数据全部取出,同Sax解析一样,我们建立tableview进行显示,这里的操作重复,就不一一展示。效果图如下:


到这里,XML的两种解析方式已经全部完毕,主要注意的就是层级关系,以及他们的特性,可以根据自己对数据的需求来选择解析方式。以达到自己想要的效果。
以上内容均属原创,如果有什么不明白的,或者我写的有什么不足,欢迎留言,谢谢。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值