有關NSXMLParser解析類庫的基本論述,可查看相關SDK幫助,以下僅僅是具體的應用操作。是以一個圖書庫應用為例,其Books.xml文檔結構如下:
1 <?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對象並讀取有關元素屬性,讀取子元素和設置它們的值給實體對象,最后不斷將實體對象添加到數組中保存。