zoukankan      html  css  js  c++  java
  • IOS的XML文件解析,利用了NSData和NSFileHandle

    如果需要了解关于文档对象模型和XML的介绍,参看 http://www.cnblogs.com/xinchrome/p/4890723.html

    读取XML

    上代码:

    NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:name];
    NSData *data = [file readDataToEndOfFile];
    [file closeFile];
        
    //create xml parser
    NSXMLParser *parser;
    parser = [[NSXMLParser alloc] initWithData:data];
        
    [parser setShouldProcessNamespaces:NO];
    [parser setShouldReportNamespacePrefixes:NO];
    [parser setShouldResolveExternalEntities:NO];
    [parser setDelegate:self];
        
    //start parse
    [parser parse];

    我们要把文件读取到NSData中,有两种方式,一种是 [[NSData alloc]initWithContentsOfFile:path],另一种是利用文件句柄直接返回一个NSData对象;然后我们用一个parser对象解析data中的数据。

    iOS中的XML解析与java语言使用的方式不一样,必须要使用代理的方式,上代码:

    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
    {
        NSLog(@"=======start element:%@=========", elementName);
        if ([elementName isEqualToString:@"skin"]) {
            NSLog(@"skin name=%@", [attributeDict objectForKey:@"name"]);
        } else if ([elementName isEqualToString:@"string"]) {
            NSLog(@"string name= %@ id=%@", [attributeDict objectForKey:@"name"], [attributeDict objectForKey:@"id"]);
        }
    }

     解析文档对象模型

    解析 XML 通常有两种方式:DOM 和 SAX,iOS SDK提供了NSXMLParser和libxml2两个类库:
    DOM解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过遍历树结构可以检索任意XML节点,读取它的属性和值。而且通常情况下,可以借助XPath,直接查询XML节点。
    SAX解析XML,是基于事件通知的模式,一边读取XML文档一边处理,不必等整个文档加载完之后才采取操作,当在读取解析过程中遇到需要处理的对象,会发出通知对其进行处理。

    特别需要注意的是,在SAX方式中,parser对象只负责解析并发送消息给代理,不会构建文档树!树必须由代理对象自己来构造。上代码:

    #import <UIKit/UIKit.h>
    #import "XMLElement.h"
    
    @interface ViewController : UIViewController <NSXMLParserDelegate>
    
    // 解析器对象
    @property (nonatomic,strong) NSXMLParser *parser;
    
    // 根元素
    @property (nonatomic,strong) XMLElement *rootElement;
    
    // 当前的元素
    @property (nonatomic,strong) XMLElement *currentElementPointer;
    
    @end
    #import "ViewController.h"
    #import "UIColor+ColorWithARGB.h"
    @interface ViewController ()
    @end
    
    @implementation ViewController
    
    -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if(self != nil){
            self.title = @"XML解析";
        }
        return self;
    }
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.view.backgroundColor = [UIColor r:0xA5 g:0xA5 b:0x52];
        NSString *xmlFilePath = [[NSBundle mainBundle]pathForResource:@"person" ofType:@"xml"];
        NSData *data = [[NSData alloc]initWithContentsOfFile:xmlFilePath];
        self.parser = [[NSXMLParser alloc]initWithData:data];
        self.parser.delegate = self;
        if([self.parser parse]){
            NSLog(@"The XML is Parsed");
            NSMutableString *str = [[NSMutableString alloc]init];
            [str appendFormat:@"%@
    ",self.rootElement.name];
            NSMutableArray *subs = self.rootElement.subElements;
            for(int i = 0;i < [subs count];i++){
                XMLElement *personElement = [subs objectAtIndex:i];
                [str appendFormat:@"	name:%@",personElement.name];
                [str appendFormat:@",text:%@
    ",personElement.text];
                NSArray *subPersonElements = personElement.subElements;
                for(int j = 0;j < [subPersonElements count];j++){
                    XMLElement *subElement = [subPersonElements objectAtIndex:j];
                    [str appendFormat:@"		name:%@",subElement.name];
                    [str appendFormat:@",text:%@
    ",subElement.text];
                }
            }
            NSLog(@"======解析结果:%@" ,str);
        }else{
            NSLog(@"Failed to parse the XML");
        }
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    // 文档开始
    -(void)parserDidStartDocument:(NSXMLParser *)parser
    {
        self.rootElement = nil;
        self.currentElementPointer = nil;
    }
    // 文档结束
    -(void)parserDidEndDocument:(NSXMLParser *)parser
    {
        self.currentElementPointer = nil;
    }
    // 元素开始
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
    {
        if(self.rootElement == nil){
            self.rootElement = [[XMLElement alloc]init];
            self.currentElementPointer = self.rootElement;
        }else{
            XMLElement *newElement = [[XMLElement alloc]init];
            newElement.parent = self.currentElementPointer;
            [self.currentElementPointer.subElements addObject:newElement];
            self.currentElementPointer = newElement;
        }
        self.currentElementPointer.name = elementName;
        self.currentElementPointer.attributes = attributeDict;
        NSLog(@"name:%@" , elementName);
    }
    // 元素结束
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
    {
        self.currentElementPointer = self.currentElementPointer.parent;
        NSLog(@"end name:%@" , elementName);
    }
    // 解析文本,会多次解析,每次只解析1000个字符,如果多月1000个就会多次进入这个方法
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
    {
        if([self.currentElementPointer.text length] > 0){
            self.currentElementPointer.text = [self.currentElementPointer.text stringByAppendingString:string];
        }else{
            self.currentElementPointer.text = [NSMutableString stringWithString:string];
        }
        NSLog(@"string:%@" , string);
    }
    
    @end

    libxml2

      上面的代码十分冗长,因为不能用parser对象直接获得文档结构。所以我们采用libxml2,http://xmlsoft.org/,它是一套默认包含在iOS SDK中的开源类库,它是基于C语言的API,所以使用起来可能不如NSXML方便。这套类库同时支持DOM和SAX解析,libxml2的SAX解析方式还是非常酷的,因为它可以边读取边解析,尤其是在从网上下载一个很大的XML文件,就可以一边下载一边对已经下载好的内容进行解析,极大的提高解析效率。

      但是基于C语言的api在代码中显得很不协调。

    GDataXML类库

      如果需要经常解析XML,第三方类库能带来更多方便。

    GDataXMLDocument读取xml文件,并且解析成为dom对象:

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"xml"];  
    NSData *xmlData = [[NSMutableData alloc] initWithContentsOfFile:filePath];  
    NSError *error;  
    GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];  
    if (doc == nil) { return nil; }  
    NSLog(@"%@", doc.rootElement);  
    //[doc release];  
    //[xmlData release];  
  • 相关阅读:
    换个角度看Salesforce之基础配置学习笔记(二)
    换个角度看Salesforce之基础配置学习笔记(一)
    C# LINQ学习笔记
    Oracle使用总结
    UML图及Visio 2010使用总结
    常见的DOS命令
    ansible笔记
    jsoncpp1.9.4源码解析
    fabric链码
    fabric数据结构
  • 原文地址:https://www.cnblogs.com/xinchrome/p/4894380.html
Copyright © 2011-2022 走看看