[iOS]XML两种解析方法

本文介绍了XML在iOS开发中的两种解析方式:SAX解析和DOM解析。SAX解析通过协议回调逐行处理,速度较慢,而DOM解析一次性加载整个XML文档,构建树形结构,速度相对较快。对于SAX解析,文章讨论了如何在解析过程中创建字典和model对象。对于DOM解析,文章提到了使用GDataXMLNode第三方库和libxml2.dylib类库的准备工作。
摘要由CSDN通过智能技术生成

XML的两种解析方法及区别:

 1.SAX 解析,逐行解析,(采用协议回调机制)速度慢 OC级别解析.

 2.DOM 解析,全体读,再分树形结构,C语言级别解析 ,是SAX解析的十几倍.

SAX 解析

解析方法

// 获取bundle包内xml 文件路径
    NSString *bundle = [[NSBundle mainBundle] pathForResource:@"Student" ofType:@"xml"];
    // 转换为二进制对象
    NSData *data = [NSData dataWithContentsOfFile:bundle];
    // 以二进制对象初始化
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
    parser.delegate = self;
    
    //开始解析
    [parser parse];
    [parser release];
关于节点名称,最好定义为静态变量,这样后面用起来方便,而且不易写错

// 方便使用,不易写错
static NSString *kRoot = @"root";
static NSString *kStuArray = @"stu_array";
static NSString *kStudent = @"student";
static NSString *kName = @"name";
static NSString *kAge = @"age";
static NSString *kTel = @"tel";
遵循 NSXMLParserDelegate 协议,并且实现下面三个方法

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

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;



在开始解析方法里,我们要判断什么时候创建字典,以及什么时候创建model对象

#pragma mark - 开始解析
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    // 判断什么时候创建字典
    if ([elementName isEqualToString:kStuArray]) {
        NSMutableDictionary *dic = [NSMutableDictionary dictionary];
        // 取出 attributeDict 里的值,存入 dic 里面
        [dic addEntriesFromDictionary:attributeDict];
        // 创建存放学生的数组
        NSMutableArray *stus = [NSMutableArray array];
        [dic setObject:stus forKey:@"array"];
        
        // dic 存入数组
        [_stuArray addObject:dic];
    }
    
    // 判断什么时候创建学生对象
    if ([elementName isEqualToString:kStudent]) {
        StudentModel *stu = [[StudentModel alloc] init];
        // 找到 学生对应的字典 里的数组
        NSMutableDictionary *lastDic = [_stuArray lastObject];
        NSMutableArray *lastArray = [lastDic objectForKey:@"array"];
        [lastArray addObject:stu];
        [stu release];
    }

取值函数我们只要将获得的字符串存起来,以结束解析时,根据判断,来确定取出来的十model的哪一个属性值,
@interface SaxXmlParser : NSObject<NSXMLParserDelegate>
{
    NSMutableArray *_stuArray;
    // 测试存值不能是成员变量,会崩溃!!!!!!!!!!!!!
//    NSString *_currentValue;
}
// 测试存值设置为属性!!!!!!!!!!!!!
@property (nonatomic,copy) NSString *currentValue;

这里要注意,接收字符串的变量,要定义为属性,不要定义为成员变量,定义为成员变量会崩溃

#pragma mark - 取值
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    // 获取字符串,传给 结束解析函数,进行判断是哪一个属性
    self.currentValue = string;
    
//    NSLog(@"解析中...");
//    NSLog(@"\nparser == %@\nstring == %@",parser,string);
}
解析结束方法里,判断取出来的字符串是model的哪一个属性

#pragma mark -结束解析
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    // 判断取出来的是 student哪个属性
    if ([elementName isEqualToString:kName]) {
        NSMutableDictionary *dic = [_stuArray lastObject];
        NSMutableArray *array = [dic objectForKey:@"array"];
        StudentModel *stu = [array lastObject];
        stu.name = _currentValue;
    }
    
    if ([elementName isEqualToString:kAge]) {
        NSMutableDictionary *dic = [_stuArray lastObject];
        NSMutableArray *array = [dic objectForKey:@"array"];
        StudentModel *stu = [array lastObject];
        stu.age = _currentValue;
    }
    
    if ([elementName isEqualToString:kTel]) {
        NSMutableDictionary *dic = [_stuArray lastObject];
        NSMutableArray *array = [dic objectForKey:@"array"];
        StudentModel *stu = [array lastObject];
        stu.tel = _currentValue;
    }
    
    // 判断解析完事
    if ([elementName isEqualToString:kRoot]) {
        NSLog(@"_stuArray == %@",_stuArray);
        // 5.调用协议方法
        [self.delegate sendArrayToMainView:_stuArray];
    }
    
//    NSLog(@"结束解析");
//    NSLog(@"\nparser == %@\nelementName == %@\nnamespaceURI == %@\nqName == %@",parser,elementName,namespaceURI,qName);
}
至此,SAX解析完成。可以用协议传值,将获得的数组传给其他页面

DOM 解析

DOM解析的准备工作:

1.准备好GDataXMLNode 第三方类,这是Google写的

2.导入libxml2.dylib 类库

3.添加 Header Search Paths 如下图


#pragma mark DOM 解析
- (void)domParser
{
    NSString *str = [[NSBundle mainBundle] pathForResource:@"Student" ofType:@"xml"];
    NSData *data =[NSData dataWithContentsOfFile:str];
    
    NSError *error = nil;
    GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:GDataXMLDocumentKind error:&error];
    if (error) {
        NSLog(@"error = %@",error);
    }
    
    // 获得根节点
    GDataXMLElement *root = [doc rootElement];
//    NSLog(@"\nroot == %@",root);
    // 获取 节点名为 stu_list 的所有 节点数组
    NSArray *array = [root elementsForName:@"stu_list"];
//    NSLog(@"array = %@",array);
    
    // // 获取 节点名为 stu_array 的所有 节点数组
    GDataXMLElement *stu_list = [array firstObject];
    NSArray *stuArray = [stu_list elementsForName:@"stu_array"];
    
    // 获取数组里 节点
    for (GDataXMLElement *stuA in stuArray) {
        // 获得属性名为 name 的节点
        GDataXMLNode *node = [stuA attributeForName:@"name"];
        // 取节点所对应的内容
        NSString *attStr = [node stringValue];
        
        // 存入字典
        NSMutableDictionary *dic = [NSMutableDictionary dictionary];
        [dic setObject:attStr forKey:@"name"];
        
        // 字典里存数组
        NSMutableArray *array = [NSMutableArray array];
        [dic setObject:array forKey:@"array"];
        
        // 将字典存入大数组
        [_stuArray addObject:dic];
        
        // 获得节点名为 student 的所有节点
        NSArray *students = [stuA elementsForName:@"student"];
        // 遍历
        for (GDataXMLElement *stu in students) {
            // 创建model 添加到数组
            StudentModel *model = [[StudentModel alloc] init];
            [array addObject:model];
            
            // 获得所有student 子节点
            NSArray *children = [stu children];
            for (GDataXMLElement *child in children) {
                // 取出节点的内容
                NSString *childValue = [child stringValue];
                
                // 判断节点名
                if ([[child name] isEqualToString:@"name"]) {
                    model.name = childValue;
                }
                if ([[child name] isEqualToString:@"age"]) {
                    model.age = childValue;
                }
                if ([[child name] isEqualToString:@"tel"]) {
                    model.tel = childValue;
                }
            }
        }
    }
}
一下是xml内数据结构

<root>
    <stu_list>
        <stu_array name = "A">
            <student>
                <name>小苹果</name>
                <age>18</age>
                <tel>120</tel>
            </student>
            <student>
                <name>蓝翔</name>
                <age>20</age>
                <tel>110</tel>
            </student>
        </stu_array>
        
        <stu_array name = "B">
            <student>
                <name>杀马特</name>
                <age>19</age>
                <tel>100</tel>
            </student>
            <student>
                <name>土豆</name>
                <age>20</age>
                <tel>120</tel>
            </student>
        </stu_array>
    </stu_list>
</root>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值