XML_SAX数据解析


XML一共有两种解析方式,SAX和DOM,本篇记录一下我在SAX数据解析时的操作。SAX解析器是对数据进行逐条的解析,这样的好处是可以查看每条的解析内容,不必等待全部解析完成,也可以发现数据中的错误。缺点就是读取速度比较慢。

citys.xml截图取一段示意:



首先创建一个NSObject:SAXxml.h    SAXxml.m

在.m.中自定义一个方法startParser,并在.h中声明

-(void)startParser{
//citys:xml文件名,xml:文件类型
 NSString *path=[[NSBundle mainBundle] pathForResource:@"citys" ofType:@"xml"];
//获取PATH路径中的数据data
 NSData *data=[NSData dataWithContentsOfFile:path];
//将数据传入解析类
 NSXMLParser *parser=[[NSXMLParser alloc] initWithData:data];
//将数据转为字符串类型NSUTF8StringEncoding枚举
 NSString *astring=[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//在.h中加入解析类NSXMLParser的协议
 parser.delegate=self;
    [parser parse];
//有alloc就要release,为了内存平衡
    [astring release];
    [parser release];
    
}

//没什么用处,就是下面调用的时候名字方便了

static NSString *Kcities=@"cities";
static NSString *Kcity=@"city";
static NSString *Kname=@"name";
static NSString *Klatitude_e6=@"latitude_e6";
static NSString *Klongitude_e6=@"longitude_e6";

//用协议里的开始解析方法elementName为city中属性的名字
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
    //如果节点(尖括号为节点)中的名字与Kcity相同
    if ([elementName isEqualToString:Kcity]) {
//创建model用于存放每个城市中的属性,如名字,经度,纬度
 SaxModel *model=[[SaxModel alloc] init];
//并将model加入到大数组中,数组在初始化创建,数组存储的就是一个个城市
 [_bigArr addObject:model];
        [model release];

    }if ([elementName isEqualToString:Kname]) {
    SaxModel *model=[_bigArr lastObject];
        NSString *name=[attributeDict objectForKey:@"data"];
        model.name=name;
    }if ([elementName isEqualToString:Klatitude_e6]) {
        SaxModel *model=[_bigArr lastObject];
        NSString *kla=[attributeDict objectForKey:@"data"];
        model.latitude_e6=kla;
    }if ([elementName isEqualToString:Klongitude_e6]) {
        SaxModel *model=[_bigArr lastObject];
        NSString *klo=[attributeDict objectForKey:@"data"];
        model.longitude_e6=klo;
    }


}
//协议中的结束解析方法

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    
   //当走到最后一个节点的时候也就是name=Kcities,将大数组里存储的各个城市通过一个自定义的协议传到root页的数组中(为了在tableView中显示)
        if ([elementName isEqualToString:Kcities]) {
        [self.delegate sendMessageToSax:_bigArr];
    }

}

SAXxml.h

//声明这个自定义的协议
@protocol SaxXmlDelegate;

@interface SaxXml : NSObject<NSXMLParserDelegate>
{//创建可变数组的成员变量用于存放city的属性也就是model
    NSMutableArray *_bigArr;
  
}
//声明刚才自定义的方法
 -(void)startParser;
//设置协议的属性
 @property(nonatomic,retain)id<SaxXmlDelegate>delegate;
@end
//自定义一个协议
@protocol SaxXmlDelegate <NSObject>
//自定义一个非必须实现的方法
@optional
 -(void)sendMessageToSax:(NSArray *)str;

@end
为了将每个city中的数据存储在一起调用,我们选择model继承与NSObject

SaxModel.h

//创建属性

@property(nonatomic,retain)NSString *name;
@property(nonatomic,retain)NSString *latitude_e6;
@property(nonatomic,retain)NSString *longitude_e6;
@property(nonatomic,retain)NSString *city;
SaxModel.m

//释放,成员变量都需要释放

-(void)dealloc{
    [_name release];
    [_latitude_e6 release];
    [_longitude_e6 release];
    [_city release];
    [super dealloc];
}


现在我们回到rootViewController

我们的需求是将XML的数据解析出并显示在tableView上

rootViewController.h

首先需要引SAXxml.h的头文件

@interface RootViewController : UIViewController
//加入自定义的协议,以及tableView的两个协议
 <SaxXmlDelegate,UITableViewDataSource,UITableViewDelegate>
{
//定义一个可变数组用于存储_bigArr传过来的数据,定义一个tableView

 NSMutableArray *_arr;
    UITableView *_aTable;
}

在rootViewController.m

中引入头文件,为了也能用model需要导入SaxModel.h,引用NewCell.h(下面会创建,这是一个自定义的cell),再就引用SaxXml.h为了传值

//一定要release
-(void)dealloc{
    [_aTable release];
    [_arr release];
    [super dealloc];
}
//这个方法是创建文件就会有的,一般初始化什么的时候写在里面,此处是为了初始化数组
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
      _arr=[[NSMutableArray alloc] init];
        
       
    }
    return self;
}
在viewDidLoad中创建tableView

//其中的高度减掉的44是导航的高度,这个因人而异
_aTable=[[UITableView alloc] initWithFrame:CGRectMake(10, 10, 320,self.view.frame.size.height-44) style:UITableViewStylePlain];
    [self.view addSubview:_aTable];
    
    _aTable.delegate=self;
    _aTable.dataSource=self;
//设置行高
 _aTable.rowHeight=150;
    
    
    [_aTable release];
//调用开始解析的方法
 [self saxParser];
//根据tableView协议调用的必须实现的方法


//根据数组中的数据算出一共多少个cell
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    
    return [_arr count];
}


//创建cell,并传值
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//重用池名字
 static NSString * cellIdentify =@"cellIdentify";
    
    //NewCell是自定义的cell的格式,下面我会写到
    NewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentify];
    //如果不为空,创建一个重用池
    if (cell ==Nil)
    {
        cell=[[[NewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentify] autorelease];
        
         }
//获取每行
 SaxModel *model=[_arr objectAtIndex:indexPath.row];
//传值
   cell.name.text=model.name;
    cell.la.text=model.latitude_e6;
    cell.lo.text=model.longitude_e6;
    
    return cell;
}

使用自定义协议中自定义的方法将SaxXml中的_bigArr,传值到rootViewController的_arr中

-(void)sendMessageToSax:(NSArray *)str{
    [_arr addObjectsFromArray:str];
 

}

创建开始解析的方法

-(void)saxParser{
    SaxXml *a=[[SaxXml alloc] init];
    a.delegate=self;
    [a startParser];
}

自定义一个cell

继承于UITableViewCell

NewCell.h

//定义每个城市的属性

@property(nonatomic,retain)  UILabel *name;
@property(nonatomic,retain) UILabel *la;
@property(nonatomic,retain)UILabel *lo;

NewCell.m

-(void)dealloc{
    [_name release];
    [_la release];
    [_lo release];
    [super dealloc];
}

定义每个cell中每个Label的坐标大小

self.name=[[UILabel alloc] initWithFrame:CGRectZero];
        [self.contentView addSubview:_name];
        [_name release];
        
        self.la=[[UILabel alloc] initWithFrame:CGRectZero];
        [self.contentView addSubview:_la];
        [_la release];
        
        
        
        self.lo=[[UILabel alloc] initWithFrame:CGRectZero];
        [self.contentView addSubview:_lo];
        [_lo release];

先将坐标创建为0,0,0,0

用一个固定方法设置具体大小

-(void)layoutSubviews{
    [_name setFrame:CGRectMake(10, 10, 100, 30)];
    [_lo setFrame:CGRectMake(10, 40, 100, 30)];
    [_la setFrame:CGRectMake(10, 70, 100, 30)];
}

解析后运行在TableView上的样子








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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值