วันศุกร์ที่ 14 มกราคม พ.ศ. 2554

XMLParser

สวัสดีครับ
สำหรับ Entry นี้จะเป็นเรื่องของ XML นะครับ
ซึ่งจริงๆ แล้ว XML Parser ก็มีคนทำให้ใช้อยู่หลายตัวนะครับ
และก็มีตัวของ Apple เองด้วย คือ NSXMLParser

การทำงานของ NSXMLParser หลังจากที่สร้าง NSXMLParser กำหนด Delegate แล้ว
เมื่อส่ง Message parse เข้าไปยัง Object ของ NSXMLParser จะเกิด Run loop ขึ้น
เราจะทำการกำหนดการทำงานต่างๆ จาก Event ที่เกิดขึ้น โดยผ่าน Delegate ของ NSXMLParser

เมื่อเริ่มทำการ Parser
– parserDidStartDocument:

เจอ Tag เปิดของ Element
– parser:didStartElement:namespaceURI:qualifiedName:attributes:

เจอ String ใน Element ปัจจุบัน
– parser:foundCharacters:

เจอ Tag ปิดของ Element
– parser:didEndElement:namespaceURI:qualifiedName:

เมื่อเกิด Error
– parser:parseErrorOccurred:

เมื่อทำการ Parser เสร็จสิ้น
– parserDidEndDocument:

และยังมี Delegate สำหรับ Event อื่นๆ ซึ่งดูได้จากใน Document
XML ที่ใช้ทดสอบจะใช้ XML จาก W3C 
ขั้นแรกก็มาดูโครงสร้างของ XML จาก File simple.xml
รูปแบบทั่วไปคือ

<breakfast_menu>
<food>
<name></name>
<price></price>
<description></description>
<calories></calories>
</food>
</breakfast_menu>



เปิด Xcode สร้าง Project ขึ้นมา (ผมใช้ชื่อ XMLParser)

Download File xml ใส่ใว้ใน Project (ไว้ใน Resources)

ไปที่ XMLParserAppDelegate.h (.h)
สร้างตัวแปรสำหรับเก็บค่าต่างๆ ตามรูปแบบทั่วไปของ XML (อาจสร้าง Class สำหรับมาใช้เก็บข้อมูล)
และ NSXMLParser ขึ้นมา

#import <UIKit/UIKit.h>

@interface XMLParserAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
NSMutableArray *_breakfast_menu;
NSMutableDictionary *_currentFood;
NSMutableString *_currentElement;
NSMutableString *_currentName;
NSMutableString *_currentPrice;
NSMutableString *_currentDescription;
NSMutableString *_currentCalories;
NSXMLParser *_xmlParser;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;

@end



ไปที่ XMLParserAppDelegate.m (.m)

ใน - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

เราจะทำการสร้าง NSXMLParser ขึ้นมา (เมื่อเจอ [_xmlParser parse]; จะเริ่มทำการ Parser)

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    // Override point for customization after application launch.
_breakfast_menu = [[NSMutableArray alloc] init];
NSURL *xmlURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"simple" ofType:@"xml"]];
_xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
[_xmlParser setDelegate:self];
[_xmlParser parse];
    [window makeKeyAndVisible];
return YES;
}



ทำการ Implement Delegate method สำหรับ Event ต่างๆ

เมื่อเกิด Error ให้แสดง Error
- (void) parser: (NSXMLParser*) parser parseErrorOccurred: (NSError *) parseError{
NSLog(@"XML Parser Error : %@", parseError);
}

เริ่มการ Parser สร้าง Object สำหรับบอก Element ปัจจุบัน
-(void)parserDidStartDocument:(NSXMLParser *)parser{
_currentElement = [[NSMutableString alloc] init];
}

เจอ Tag เปิดกำหนดค่าของ _currentElement เพื่อนำไปตรวจสอบชนิดของ Element ที่ทำงานอยู่
ถ้าเป็น Tag food สร้าง Object สำหรับเก็บรายละเอียด
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
[_currentElement setString:elementName];
if([elementName isEqualToString: @"food"]){
_currentFood = [[NSMutableDictionary alloc] init];
_currentName = [[NSMutableString alloc] init];
_currentPrice = [[NSMutableString alloc] init];
_currentDescription = [[NSMutableString alloc] init];
_currentCalories = [[NSMutableString alloc] init];

}
}

เจอ Tag ปิดทำการเก็บค่าที่ได้
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if([elementName isEqualToString: @"food"]){
[_breakfast_menu addObject: _currentFood];
[_currentFood release];

}else if([elementName isEqualToString: @"name"]){
[_currentFood setObject: _currentName forKey: @"name"];
[_currentName release];
}else if([elementName isEqualToString: @"price"]){
[_currentFood setObject: _currentPrice forKey: @"price"];
[_currentPrice release];
}else if([elementName isEqualToString: @"description"]){
[_currentFood setObject: _currentDescription forKey: @"description"];
[_currentDescription release];
}else if([elementName isEqualToString: @"calories"]){
[_currentFood setObject: _currentCalories forKey: @"calories"];
[_currentCalories release];

}
}

เจอข้อมูลระหว่าง Tag
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if(![[string stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString: @""]){
if([_currentElement isEqualToString: @"name"]){
[_currentName appendString: string];
}else if([_currentElement isEqualToString: @"price"]){
[_currentPrice appendString: string];
}else if([_currentElement isEqualToString: @"description"]){
[_currentDescription appendString: string];
}else if([_currentElement isEqualToString: @"calories"]){
[_currentCalories appendString: string];
}
}
}

จบการทำ Parser
- (void)parserDidEndDocument:(NSXMLParser *)parser {
for (NSMutableDictionary *food in _breakfast_menu){
NSLog(@"\n\n");
NSLog(@"Name        : %@", [food objectForKey: @"name"]);
NSLog(@"Price       : %@", [food objectForKey: @"price"]);
NSLog(@"Description : %@", [food objectForKey: @"description"]);
NSLog(@"Calories    : %@", [food objectForKey: @"calories"]);
}
[_currentElement release];
}



ลอง Build & Run ดูผลใน Debugger Console


ไม่มีความคิดเห็น:

แสดงความคิดเห็น