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

IOS 详解NSXMLParser方法解析XML数据方法

2013-05-15 12:31 543 查看


Xml数据格式

[html] view
plaincopy

<?xml version="1.0" encoding="UTF-8"?>  

<Books>  

<Book id="1">  

<title>Circumference</title>  

<author>Nicholas Nicastro</author>  

<summary>Eratosthenes and the Ancient</summary>  

</Book>  

<Book id="2">  

<title>Copernicus Secret</title>  

<author>Jack Repcheck</author>  

<summary>How the scientific revolution began</summary>  

</Book>  

<Book id="3">  

<title>Angels and Demons</title>  

<author>Dan Brown</author>  

<summary>Robert Langdon is summoned to a Swiss</summary>  

</Book>  

</Books>  

显然在这个xml中包括三本书的一些基本数据:id   title   author   summary  解析的过程就是将这些数据提取出来。

先简单介绍一下xml数据解析吧。xml数据的解析一般有两种方式:SAX(Simple API for XML)和DOM (Document Object Model),事件和文档。

[align=left]dom实现的原理是把整个xml文档一次性读出,放在一个树型结构里。在需要的时候,查找特定节点,然后对节点进行读或写。他的主要优势是实现简单,读写平衡;缺点是比较占内存,因为他要把整个xml文档都读入内存,文件越大,这种缺点就越明显。[/align]
[align=left][/align]
sax的实现方法和dom不同。他只在xml文档中查找特定条件的内容,并且只提取需要的内容。这样做占用内存小,灵活。

NSXMLParser 实现的是sax方法解析xml文件。

下面进入主题介绍如何对xml进行解析:

一、将上面的xml数据保存为Books.xml作为本地xml数据,并导入项目中。

二、由于book中含有几个属性,所以这里第一个book类。

Book.h文件:

[cpp] view
plaincopy

#import <Foundation/Foundation.h>  

  

@interface Book : NSObject  

  

@property (nonatomic, readwrite) NSInteger bookID;  

@property (nonatomic, retain) NSString  *title;  

@property (nonatomic, retain) NSString  *author;  

@property (nonatomic, retain) NSString  *summary;  

  

@end  

Book.m文件

[cpp] view
plaincopy

#import "Book.h"  

  

@implementation Book  

  

@synthesize bookID;  

@synthesize title;  

@synthesize author;  

@synthesize summary;  

  

@end  

三、要实现对xml数据的解析实际上是通过实现NSXMLParserDelegate委托中的几个方法。

[cpp] view
plaincopy

#pragma mark xmlparser    

//step 1 :准备解析    

- (void)parserDidStartDocument:(NSXMLParser *)parser    

{    

   

}    

//step 2:准备解析节点    

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

{    

   

}    

//step 3:获取首尾节点间内容    

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

{    

       

}    

    

//step 4 :解析完当前节点    

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

{    

     

}    

    

//step 5:解析结束    

- (void)parserDidEndDocument:(NSXMLParser *)parser    

{    

   

}    

//step 6:获取cdata块数据    

- (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock    

{    

  

}    

在实现xml解析过程以上方法中的step3 、4、5是必须的,而step1、5可选。

下面分别介绍:

Step 1: 在开始解析之前的一些准备工作,例如初始化一些存储变量。在我的这个例子中,使用了一个Book实例变量来存储一本书(也即是一组信息),一个可变数组来存储这三本书(即每一组信息都当成这个数组中的一个元素),(此次要注意理解数据变量之间的关系),其他变量就暂不介绍啦(待会看源代码就可以了)。

Step 2: 当解析器遇到xml的根标签和一组信息的开始标签时就开始调用这个方法,在这个xml文件中,遇到Books(xml文件的根标签),Book(一组信息的开始标签)时就会调用这个方法。那么也就可以知道这个方法在程序运行过程中被调用了多次。那么就可以用 if 语句判断遇到的是Books还是Book,然后做一些相应的操作(具体的话待会看源代码)。

[cpp] view
plaincopy

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

{    

   

}    

注意其中的参数:elementName表示遇到的标签,在这个程序中会遇到的是Books和Book;  解析到一个标签时,开始的 标签可能会有一些属性,例如在这里<Book id="1">

那么id就是属性啦,在这个方法中他是用一个字典来保存的即(NSDictionary *)attributeDict,那么对这个字典操作就可以得到你要的value和key啦。

Step 3:当解析器找到开始标签和结束标签之间的字符时,就调用这个方法,读取其中的内容。 注意:这里读取到的string在这个函数里面我们并不知道是那个属性的内容,意思就是假如string的内容是Circumference(Book 的title),但是我们不知道这个是title的内容;那么在哪里才知道,然后对它进行存储操作呢,不要着急,就是Step4啦!

Step 4:当解析器读到结束标签时,就会调用这个方法。例如读到Books,Book,title等。那么对读到的标签进行判断后就可以进行存储操作啦!

[cpp] view
plaincopy

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

{    

     

}   

这里标签参数就是elementName。

Step 5:对整个xml文件解析结束后的一些操作。

Step 6:这个暂不解释(我还没有用到)。

四、下面就是上代码的时候啦

.h文件

[cpp] view
plaincopy

#import <UIKit/UIKit.h>  

  

@class AppDelegate,Book;  

@interface ViewController : UIViewController <NSXMLParserDelegate> {  

      

    NSMutableString *currentElementValue;  //用于存储元素标签的值  

      

    NSMutableArray *books;  //用于存储一组书籍  

      

    Book *aBook;  //书籍实例,代表一本书  

      

    BOOL storingFlag; //查询标签所对应的元素是否存在  

      

    NSArray *elementToParse;  //要存储的元素  

}  

- (IBAction)xmlButton:(id)sender;  

  

@end  

说明:这里我用一个按键来触发xml解析。

.m文件

[cpp] view
plaincopy

#import "ViewController.h"  

#import "AppDelegate.h"  

  

@interface ViewController ()  

  

@end  

  

@implementation ViewController  

  

- (void)viewDidLoad  

{  

    [super viewDidLoad];  

    // Do any additional setup after loading the view, typically from a nib.  

    //初始化要解析的元素标签  

    elementToParse = [[NSArray alloc] initWithObjects:@"title",@"author",@"summary", nil];  

}  

  

- (void)didReceiveMemoryWarning  

{  

    [super didReceiveMemoryWarning];  

    // Dispose of any resources that can be recreated.  

}  

  

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

    if([elementName isEqualToString:@"Books"]) {  

        //Initialize the array.  

        //在这里初始化用于存储最终解析结果的数组变量,我们是在当遇到Books根元素时才开始初始化  

        books = [[NSMutableArray alloc] init];  

        }  

    else if([elementName isEqualToString:@"Book"]) {  

          

        //Initialize the book.  

        //当碰到Book元素时,初始化用于存储Book信息的实例对象aBook  

          

        aBook = [[Book alloc] init];  

          

        //Extract the attribute here.  

        //从attributeDict字典中读取Book元素的属性  

          

        aBook.bookID = [[attributeDict objectForKey:@"id"] integerValue];  

          

        NSLog(@"ID:%i", aBook.bookID);  

        }  

    storingFlag = [elementToParse containsObject:elementName];  //判断是否存在要存储的对象  

}  

  

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

    // 当用于存储当前元素的值是空时,则先用值进行初始化赋值  

    // 否则就直接追加信息  

    if (storingFlag) {  

        if (!currentElementValue) {  

            currentElementValue = [[NSMutableString alloc] initWithString:string];  

        }  

        else {  

            [currentElementValue appendString:string];  

        }  

    }  

      

}  

  

// 这里才是真正完成整个解析并保存数据的最终结果的地方  

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

      

    if ([elementName isEqualToString:@"Book"]) {  

        [books addObject:aBook];  

        aBook = nil;  

    }  

      

    if (storingFlag) {  

        //去掉字符串的空格  

        NSString *trimmedString = [currentElementValue stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];  

          

        //将字符串置空  

        [currentElementValue setString:@""];  

          

        if ([elementName isEqualToString:@"title"]) {  

            aBook.title = trimmedString;  

            NSLog(@"title :%@",aBook.title);  

        }  

        if ([elementName isEqualToString:@"author"]) {  

            aBook.author = trimmedString;  

            NSLog(@"author :%@",aBook.author);  

        }  

        if ([elementName isEqualToString:@"summary"]) {  

            aBook.summary = trimmedString;  

            NSLog(@"summary :%@",aBook.summary);  

        }  

    }  

      

}  

  

- (IBAction)xmlButton:(id)sender {  

    //打开xml文件,读取数据到NSData  

    NSString *path = [[NSBundle mainBundle] pathForResource:@"Books" ofType:@"xml"];  

    NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path];  

    NSData *data = [file readDataToEndOfFile];  

    [file closeFile];  

      

    //测试从xml接受到的数据  

    NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];  

    NSLog(@"%@",dataString);  

      

    NSXMLParser *m_parser = [[NSXMLParser alloc] initWithData:data];  

    //设置该类本身为代理类,即该类在声明时要实现NSXMLParserDelegate委托协议  

    [m_parser setDelegate:self];  //设置代理为本地  

      

    BOOL flag = [m_parser parse]; //开始解析  

    if(flag) {  

        NSLog(@"解析指定路径的xml文件成功");  

    }  

    else {  

        NSLog(@"解析指定路径的xml文件失败");  

    }      

}  

@end  

转载自:http://blog.csdn.net/crayon_dys/article/details/8738811
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: