您的位置:首页 > 移动开发 > IOS开发

iOS开发实践之XML

2016-01-25 23:31 561 查看
xml与json的对比,前面文章已经提供参考,至于xml的语法结构也不在这详述。 直奔iOS中解析xml的方法。

iOS中的XML解析(Dom和SAX)
Dom方式使用的是文档对象模型解析,它首先要将xml文件整个读入内存中,然后再来构建Dom对象,在DOM对象里,xml文件中的所有元素都可以当做节点(Node)对象来处理。这种方式优点是方便对文档进行增加、删除、修改、添加等操作,缺点是它首先要将整个文件读入内存中在解析,如果文件大。会很消耗内存,并且它的执行速度慢。
SAX解析XML文件采用事件驱动的方式进行,也就是说,SAX是逐行扫描文件,遇到符合条件的设定条件后就会触发特定的事件,回调你写好的事件处理程 序。使用SAX的优势在于其解析速度较快,占用内存较少(相对于DOM而言)。而且SAX在解析文件的过程中得到自己需要的信息后可以随时终止解析,并不 一定要等文件全部解析完毕。凡事有利必有弊,其劣势在于SAX采用的是流式处理方式,当遇到某个标签的时候,它并不会记录下以前所遇到的标签,也就是说, 在处理某个标签的时候,所能够得到的信息就是标签的名字和属性,至于标签内部的嵌套结构,上层标签、下层标签以及其兄弟节点的名称等等与其结构 相关的信息都是不得而知的。实际上就是把XML文件的结构信息丢掉了,如果需要得到这些信息的话,只能你自己在程序里进行处理了。所以相对DOM而 言,SAX处理XML文档没有DOM方便,SAX处理的过程相对DOM而言也比较复杂。

总结:
DOM:一次性将整个XML文档加载进内存,比较适合解析小文件
SAX:SAX采用事件驱动,从根元素开始,按顺序一个元素一个元素往下解析,比较适合解析大文件。

解析方法:

苹果原生
NSXMLParser:SAX方式解析,使用简单

第三方框架
libxml2:纯C语言,默认包含在iOS SDK中,同时支持DOM和SAX方式解析
GDataXML:DOM方式解析,由Google开发,基于libxml2

XML解析方式的选择建议
大文件:NSXMLParser、libxml2
小文件:GDataXML

GDataXML:

常用的类
GDataXMLDocument:代表整个XML文档
GDataXMLElement:代表文档中的每个元素
常用方法:
elementsForName:根据元素名称得到元素节点

attributeForName:方法可以获得属性值
更多的操作xml的方法和属性,查阅GDataXMLNode.h

使用步骤:
1、下载GDataXMLNode ,下载地址:http://download.csdn.net/detail/zhixinhuacom/9417644,并 解压将其中的GDataXMLNode.h 和 GDataXMLNode.m文件拖到项目中。
2、由于GDataXML基于libxml2库,因此要导入libxml2



3、设置libxml2的头文件搜索路径(为了能找到libxml2库的所有头文件)
Head Search Path中加入/usr/include/libxml2



4、设置链接参数(自动链接libxml2库)
Other Linker Flags中加入-lxml2



5、如果报arc错误,则设置GDataXML编译参数



6、导入#import "GDataXMLNode.h" 头文件就可以使用了。

例子:
解析下面格式的xml




-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/myService/video?type=XML"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        //1、加载xml数据
        
        GDataXMLDocument *document = [[GDataXMLDocument alloc]initWithData:data options:0 error:nil];
        //2、获取xml根元素(videos)
        GDataXMLElement *root = document.rootElement;
        
//        //元素子节点个数(不包括子节点下的节点)
//        NSInteger childCount = root.childCount;
//        //元素名称
//        NSString *elementName =  root.name;
//        //节点内容字符串
//        NSString *xmlStr = root.XMLString;
//        NSLog(@"childCount=%ld\nelementName=%@\nxmlStr=%@",childCount,elementName,xmlStr);
        
        //3、获取根元素的所有video元素
        NSArray *elements = [root elementsForName:@"video"];
        for (GDataXMLElement *element in elements) {
            //4、获取属性植
            NSString *idStr = [element attributeForName:@"id"].stringValue;
            NSString *name = [element attributeForName:@"name"].stringValue;
            NSString *length = [element attributeForName:@"length"].stringValue;
            NSString *image = [element attributeForName:@"image"].stringValue;
            NSString *url = [element attributeForName:@"url"].stringValue;
            
            NSLog(@"id=%@",idStr);
            NSLog(@"name=%@",name);
            NSLog(@"length=%@",length);
            NSLog(@"image=%@",image);
            NSLog(@"url=%@",url);
        }
    }];
}




NSXMLParser:

NSXMLParser采取的是SAX方式解析,特点是事件驱动,下面情况都会通知代理:
(1)当扫描到文档(Document)的开始与结束
(2)当扫描到元素(Element)的开始与结束

一:使用步骤:
1、传入XML数据,创建解析器
NSXMLParser *parser = [[NSXMLParseralloc]
initWithData:data];

2、设置代理,监听解析过程
parser.delegate =self;

3、开始解析
[parserparse];

二:NSXMLParserDelegate常用代理方法:

当扫描到文档的开始时调用(开始解析)
- (void)parserDidStartDocument:(NSXMLParser *)parser

当扫描到文档的结束时调用(解析完毕)
- (void)parserDidEndDocument:(NSXMLParser *)parser

当扫描到元素的开始时调用(attributeDict存放着元素的属性)
- (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

例子:同样解析上面格式的xml

#import "ViewController.h"

@interface ViewController ()<NSXMLParserDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/myService/video?type=XML"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        
        //1、传入xml,创建解析器
        NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];
        
        //2、设置代理、监听解析过程
        parser.delegate = self;
        
        //3、开始解析
        [parser parse];
    }];
}

#pragma mark NSXMLParserDelegate代理方法
//当扫描到元素的开始时调用(attributeDict存放着元素的属性)
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{
    NSLog(@"===========%@元素开始解析========",elementName);
    if ([@"videos" isEqualToString:elementName]) {
        NSLog(@"%@是根节点",elementName);
        return;
    }
    
    NSString *idStr = attributeDict[@"id"];
    NSString *name = attributeDict[@"name"];
    NSString *length = attributeDict[@"length"];
    NSString *image = attributeDict[@"image"];
    NSString *urlStr = attributeDict[@"url"];
    
    NSLog(@" \n id=%@ \n name=%@\n length=%@ \n image=%@ \n url=%@",idStr,name,length,image,urlStr);
   
};

//当扫描到元素的结束时调用
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    NSLog(@"===========%@元素解析结束========",elementName);
    
}

//当扫描到文档的开始时调用(开始解析)
-(void)parserDidStartDocument:(NSXMLParser *)parser{
    NSLog(@"parserDidStartDocument=====开始解析=======");
}

//当扫描到文档的结束时调用(解析完毕)
-(void)parserDidEndDocument:(NSXMLParser *)parser{
    NSLog(@"parserDidEndDocument=====解析完毕========");
}

@end


解析输入结果:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: