[iOS][Web]iPhoneアプリケーションとサーバ間の通信(その4) | Cocoa練習帳

[iOS][Web]iPhoneアプリケーションとサーバ間の通信(その4)

先日のRESTの回では、取得したXMLデータを解析していなかったので、今回は、解析に挑戦だ。




XMLデータへのアクセス方法には、DOMとSAXの2種類があるが、iOSではCocoaのフレームワークで用意されているのはSAXに対応するNSXMLParserのみだ。もちろん、DOMも利用できるか、Cocoaのフレームワークなので手軽だという事と、iOS機器の貧弱なリソース(メモリetc)を考えて、NSXMLParserを利用する方法を紹介する。




ビー・コントローラーにNSXMLParserDelegateプロトコルを追加し、解析で使用するプロパティを追加する。




@interface ViewController : UIViewController <NSXMLParserDelegate>

@property (assign, nonatomic) BOOL                  inPersonElement;
@property (assign, nonatomic) BOOL                  inNameElement;
@property (assign, nonatomic) BOOL                  inAgeElement;
@property (strong, nonatomic) NSMutableString       *name;
@property (strong, nonatomic) NSMutableString       *age;

@end



返ってきたデータdataをパースする。ARCのおかげで、記述が簡素になっている。




        if (data) {
            NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:data];
            xmlParser.delegate = self;
            [xmlParser parse];
        }



パースで利用する、委任メソッドだ。




- (void)parserDidStartDocument:(NSXMLParser *)parser
{
    self.inPersonElement = NO;
    self.inNameElement = NO;
    self.inAgeElement = NO;
}
 
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
}
 
- (void)parser:(NSXMLParser *)parser
    didStartElement:(NSString *)elementName
    namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qualifiedName
    attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:@"person"]) {
        self.inPersonElement = YES;
    }
    else if ([elementName isEqualToString:@"name"]) {
        self.inNameElement = YES;
        self.name = [[NSMutableString alloc] init];
    }
    else if ([elementName isEqualToString:@"age"]) {
        self.inAgeElement = YES;
        self.age = [[NSMutableString alloc] init];
    }
}
 
- (void)parser:(NSXMLParser *)parser
    didEndElement:(NSString *)elementName
    namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qName
{
    if ([elementName isEqualToString:@"person"]) {
        self.inPersonElement = NO;
        NSLog(@"person(name[%@], age[%@])", self.name, self.age);
    }
    else if ([elementName isEqualToString:@"name"]) {
        self.inNameElement = NO;
    }
    else if ([elementName isEqualToString:@"age"]) {
        self.inAgeElement = NO;
    }
}
 
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if (self.inPersonElement) {
    }
     
    if (self.inNameElement) {
        [self.name appendString:string];
    }
    else if (self.inAgeElement) {
        [self.age appendString:string];
    }
}



NSXMLParserで解析する場合、ステータスを覚えておいて、ステータスに合わせて得られた情報を扱う必要があるが、この程度の簡素なデータでは、特に問題はないと思う。




ソースコード
GitHubからどうぞ。

https://github.com/murakami/workbook/tree/master/ios/REST - GitHub


関連情報
CHAPTER 5 Representational State Transfer (REST)

Fieldingの論文。

iOSプログラミング逆引きリファレンス108 ~知りたいことがすぐわかるiPhoneプログラミングテクニック~

全面的に、この書籍を参考にしています。助かります!

URL Loading System Programming Guide

Event-Driven XML Programming Guide

Developerサイトの情報。