IOS(一)XML数据解析

本文深入探讨了XML解析技术中的两种主要方式——DOM和SAX。通过实例展示了如何使用这两种方法解析XML数据,包括数据结构、解析流程以及关键代码实现。重点介绍了如何在实际应用中灵活选择合适的解析策略。
摘要由CSDN通过智能技术生成

解析 XML 通常有两种方式,DOM 和 SAX:

  • DOM解析XML时,读入整个XML文档并构建一个树结构(节点树),通过遍历树结构可以得到任意XML节点,读取它的属性和值,直接查询XML节点。
  • SAX解析XML时,是基于事件通知的模式,一边读取XML文档一边处理,不必等整个文档加载完之后才采取操作,采用逐行读取,速度比较慢。

XML的数据格式:

      第一种: 属性在字典“data”中保存

<xml_api_reply version="1">
	<cities>
		<city>
			<name data="保定"></name>
			<latitude_e6 data="38849998"></latitude_e6>
			<longitude_e6 data="115569999"></longitude_e6>
		</city>
		<city default="true">
			<name data="北京"></name>
			<latitude_e6 data="39930000"></latitude_e6>
			<longitude_e6 data="116279998"></longitude_e6>
		</city>



    第二种: 属性在两个尖括号中间
<students>
    <student>
        <number>1</number>
        <name>王百惠</name>
        <sex>女</sex>
        <phone>110</phone>
    </student>



XML解析之SAX解析:

    SAX解析是通过NSXMLParser解析的解析方式。NSXMLParser采用了委托设计模式,因此他的实现类需要采用协议并支持委托。NSXMLParser解析XML需要遵循NSXMLParserDelegate协议。
   简单地说,SAX解析就是从头到尾的逐行读取文档,通过协议判断读取到值时采取操作,顺序是先读取头标签在读取结束标签。这样就可以取到标签所对应的值了。下面我们来看一下实现这样功能的主要代码:

-(void)startParser{    
    NSString * path = [[NSBundle mainBundle] pathForResource:@"Students" ofType:@"xml"];
    
    NSData * data =[[ NSData alloc] initWithContentsOfFile:path];
    
    NSXMLParser * parser= [[NSXMLParser alloc] initWithData:[[NSData alloc] 
             initWithContentsOfFile:path]];
    parser.delegate = self;
    [parser parse];
}

准备工作,将XML文件导入工程,在开始解析之前,我们要先获取它的地址,并初始化一个,要遵循协议,我们就是通过这个协议中的方法,来解析数据以获取XML中的值。
//获取内容
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    
    NSLog(@"found =%@",string);
    
    //系统传来的参数   内存管理为autorealese   为0    要copy或者retain一份
    _currentValue = [string copy];
    
}

//标签名
static NSString * kStudent = @"student";
static NSString * kNumber = @"number";

//协议 开始解析
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:
(NSDictionary *)attributeDict{
    if ([elementName isEqualToString:kStudent]) {
        SaxModel *model = [[SaxModel alloc] init];
        [_peopleArray addObject:model];
        [model release];
    }  
}

//协议  解析结束   赋值
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    SaxModel * model = [_peopleArray lastObject];
    if ([elementName isEqualToString:kNumber]) {
        model.number = _currentValue;
    }if ([elementName isEqualToString:kName]) {
        model.name = _currentValue;
    }if ([elementName isEqualToString:kstudents]) {
        [self.delegate sendMessageTorootwithArr:_peopleArray];
    }
    }

   这三个是NSXMLParserDelegate的内容,也是我们用来解析的最关键的3个协议,分别对应XML中的一个属性和两个element。当XML的格式为前面所说的第一种时,我们取值也可以省略几步,直接在- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{}这个协议中获取 ,因为你要的信息就再第一个标签内,最后只要判断最后一个数据的节点名就可以了。标签是为了方便,避免element的名字混淆。

而当一个数据的属性过多时,而且在另外的类中使用,对我们传值来说就困难了,所以我们一般会将一个数据的各种属性写成一个model,再将所有的model加到一个数组中,通过数组保存。
     若是要传值(controller之间),在SAX解析中 ,我们是通过自己写协议来实现的。如下:
#import <Foundation/Foundation.h>

@protocol SaxXmlparserDelegate;
@interface SaxXmlparser : NSObject<NSXMLParserDelegate>
@property(nonatomic,assign) id <SaxXmlparserDelegate>delegate;
@end
@protocol SaxXmlparserDelegate <NSObject>
-(void)sendMessageTorootwithArr:(NSArray *)array;
@end

XML解析之Dom解析:
       下面我们来看看dom解析是如何的一个过程吧。

-(void)domParser{
    NSString * path = [[NSBundle mainBundle] pathForResource:@"Students" ofType:@"xml"];
    NSData * data = [NSData dataWithContentsOfFile:path];
    NSError * error = Nil;
    GDataXMLDocument * document = [[GDataXMLDocument alloc] initWithData:data options:
   GDataXMLDocumentKind error:&error];
   
    if (error) {
        NSLog(@"%@",error);
    }
    //获得节点名
    GDataXMLElement * root = [document rootElement];   
    //根据子节点  获得子节点数组
    NSArray * arr = [root elementsForName:@"student"];
   
    //获得根节点
    NSString * str = [root name];
    NSLog(@"%@",str);
    
    for (GDataXMLElement * element in arr) {
        NSArray * leaf = [element children];
        
        NSLog(@"%@",leaf);
        for (GDataXMLElement * endleaf in leaf) {
            //获得叶子节点中的内容
            NSString * str = [endleaf stringValue];
            NSLog(@"%@",str);
        }
    }
    
    
}
     这里我们引用了GDataXMLNode第三方类。
    同样,通过地址找到document,再获得根节点,根据数据的结构,一次层级的取得下一级的节点,一直取到一整个model的属性的节点时,将这几个节点的内容放到model里面(通过遍历的方法),最后的一个或者若干个数组(本例中只有一个数组),里面包含了一个个的model,而这些,就是我们解析出来的数据。要注意管理循环内的内存管理,model在哪里要初始化,在哪里不用,请参考上例。以上是我对于XML解析的一点理解,希望能够帮到大家。以后会陆续更新。。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值