iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど
先日の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で解析する場合、ステータスを覚えておいて、ステータスに合わせて得られた情報を扱う必要があるが、この程度の簡素なデータでは、特に問題はないと思う。