<?xml version="1.0" encoding="UTF-8"?>
2 <Books>
3 <Book id="1">
4 <title>Circumference</title>
5 <author>Nicholas Nicastro</author>
6 <summary>Eratosthenes and the Ancient</summary>
7 </Book>
8 <Book id="2">
9 <title>Copernicus Secret</title>
10 <author>Jack Repcheck</author>
11 <summary>How the scientific revolution began</summary>
12 </Book>
13 <Book id="3">
14 <title>Angels and Demons</title>
15 <author>Dan Brown</author>
16 <summary>Robert Langdon is summoned to a Swiss</summary>
17 </Book>
18 </Books>
从其文档结构我们可以看出,要定义一个Book实体类描述具体的书籍信息,其中用于存储的相关xml文档元素的实例变量与对应元素同名(本例:title、author、summary),另外还有个bookID实例变量存储Book元素标签的属性id值。具体Book实体类的定义如下:
1 // Book.h
2 #import <UIKit/UIKit.h>
3 @interface Book:NSObject {
4 NSInteger bookID;
5 NSString *title;
6 NSString *author;
7 NSString *summary;
8 }
9
10 @property (nonatomic, readwrite) NSInteger bookID;
11 @property (nonatomic, retain) NSString *title;
12 @property (nonatomic, retain) NSString *author;
13 @property (nonatomic, retain) NSString *summary;
14
15 @end
16
17 //Book.m
18 #import "Book.h"
19 @implementation Book
20 @synthesize title,author,summary,bookID;
21
22 - (void)dealloc {
23 [summary release];
24 [author release];
25 [title release];
26 [super dealloc];
27 }
28 @end
由于例子中的xml文档结构表明会有很多书籍,即Book实体类的实例对象会有很多。所以我们要在应用程序中声明一个可变数组来存储这些信息,如下代码表明:在应用程序委托类中声明了一个可变数组books。
// AppDelegate.h
@interface AppDelegate : NSObject <UIApplicationDelegate> {
//默认缺省的实例变量
NSMutableArray *books;
}
//默认缺省的属性定义
@property (nonatomic, retain) NSMutableArray *books;
@end
为了代码的清晰,我们可以再声明一个代理类XMLParser,在当NSXMLParser实例对象指定委托时会用到。
// XMLParser.h
#import <UIKit/UIKit.h>
@class AppDelegate, Book;
@interface XMLParser : NSObject {
NSMutableString *currentElementValue; //用于存储元素标签的值
AppDelegate *appDelegate;
Book *aBook; //书籍实例
}
- (XMLParser *)initXMLParser; //构造器
@end
// XMLParser.m
- (XMLParser *)initXMLParser {
[super init];
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
return self;
}
这整个XMLParser类的实现代码如下:
1 //XMLParser.m
2 #import "XMLParser.h"
3 #import "XMLAppDelegate.h"
4 #import "Book.h"
5
6 @implementation XMLParser
7
8 - (XMLParser *) initXMLParser {
9
10 [super init];
11
12 appDelegate = (XMLAppDelegate *)[[UIApplication sharedApplication] delegate];
13
14 return self;
15 }
16
17 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
18 namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
19 attributes:(NSDictionary *)attributeDict {
20
21 if([elementName isEqualToString:@"Books"]) {
22 //Initialize the array.
23 //在这里初始化用于存储最终解析结果的数组变量,我们是在当遇到Books根元素时才开始初始化,有关此初始化过程也可以在parserDidStartDocument 方法中实现
24 appDelegate.books = [[NSMutableArray alloc] init];
25 }
26 else if([elementName isEqualToString:@"Book"]) {
27
28 //Initialize the book.
29 //当碰到Book元素时,初始化用于存储Book信息的实例对象aBook
30 aBook = [[Book alloc] init];
31
32 //Extract the attribute here.
33 //从attributeDict字典中读取Book元素的属性
34 aBook.bookID = [[attributeDict objectForKey:@"id"] integerValue];
35
36 NSLog(@"Reading id value :%i", aBook.bookID);
37 }
38
39 NSLog(@"Processing Element: %@", elementName);
40 }
41 /* 可以看出parser:didStartElement:namespaceURI:qualifiedName:attributes方法实现的就是在解析元素开始标签时,进行一些初始化流程 */
42
43 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
44 // 当用于存储当前元素的值是空时,则先用值进行初始化赋值
45 // 否则就直接追加信息
46 if(!currentElementValue)
47 currentElementValue = [[NSMutableString alloc] initWithString:string];
48 else
49 [currentElementValue appendString:string];
50
51 NSLog(@"Processing Value: %@", currentElementValue);
52
53 }
54
55 // 这里才是真正完成整个解析并保存数据的最终结果的地方
56 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
57 namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
58
59 if([elementName isEqualToString:@"Books"])
60 return;
61
62 //There is nothing to do if we encounter the Books element here.
63 //If we encounter the Book element howevere, we want to add the book object to the array 遇到Book元素的结束标签,则添加book对象到设置好的数组中。
64 // and release the object.
65 if([elementName isEqualToString:@"Book"]) {
66 [appDelegate.books addObject:aBook];
67
68 [aBook release];
69 aBook = nil;
70 }
71 else
72 // 不是Book元素时也不是根元素,则用 setValue:forKey为当前book对象的属性赋值
73 [aBook setValue:currentElementValue forKey:elementName];
74
75 [currentElementValue release];
76 currentElementValue = nil;
77 }
78
79 - (void) dealloc {
80
81 [aBook release];
82 [currentElementValue release];
83 [super dealloc];
84 }
85
86 @end
只要没有碰到文档结束符,解析器会一而再,再而三的不断呼叫此三个回调函数进行循环:开始初始化book对象并读取有关元素属性,读取子元素和设置它们的值给实体对象,最后不断将实体对象添加到数组中保存。