libxmlを使用したNSDictionaryでのXMLの解析

iPhoneのプロジェクトでは、サーバーからの多数のxml応答を解析する必要がありました。 NSDictionaryでXMLを解析するためのソリューションを共有したいと思います。



フォームのXML(結果の例では、いくつかのルート要素が存在する必要があります):

<result success="true">

<item>Value</item>

<item attr="val" />

<item code="item">value</item>

</result>







以下に変換されます:

 NSDictionary { "name" => "result", "attr" => NSDictionary { "success" => "true" }, "child" => NSArray { 0 => NSDictionary { "name" => "item", "value" => "value" }, 1 => NSDictionary { "name" => "item", "attr" => NSDictionary { "code" => "item" } }, 2 => NSDictionary { "name" => "item", "attr" => NSDictionary { "attr" => "val" }, "value" => "value" } } 
      





NSDictionary { "name" => "result", "attr" => NSDictionary { "success" => "true" }, "child" => NSArray { 0 => NSDictionary { "name" => "item", "value" => "value" }, 1 => NSDictionary { "name" => "item", "attr" => NSDictionary { "code" => "item" } }, 2 => NSDictionary { "name" => "item", "attr" => NSDictionary { "attr" => "val" }, "value" => "value" } }







実際にはメソッド自体:

 /*  xml   */ - (NSDictionary *)xmlToDict { NSDictionary *resultDict = [NSDictionary dictionary]; if (self.content != nil) { xmlDocPtr doc = xmlParseMemory([self.content bytes], [self.content length]); if (!doc) { //    NSLog(@"error"); } else { xmlNode *root = NULL; root = xmlDocGetRootElement(doc); resultDict = [NSDictionary dictionaryWithDictionary:[self getNodeInfo:root]]; xmlFree(root); } } return resultDict; } /*   xml ,  */ -(NSDictionary *)getNodeInfo:(xmlNode *)node { NSMutableDictionary *itemDict = [[[NSMutableDictionary alloc] initWithCapacity:1] autorelease]; xmlChar *value = NULL; xmlAttr *attribute = NULL; if (node && node->name && ![[NSString stringWithCString:(char *)node->name encoding:NSUTF8StringEncoding] isEqualToString:@"text"]) { /*   */ value = (xmlChar*)node->name; [itemDict setObject:[NSString stringWithCString:(char *)value encoding:NSUTF8StringEncoding] forKey:@"name"]; xmlFree(value); /*   */ attribute = node->properties; NSMutableDictionary *attrDict = [[NSMutableDictionary alloc] initWithCapacity:1]; while(attribute && attribute->name && attribute->children) { value = xmlNodeListGetString(node->doc, attribute->children, 1); [attrDict setObject:[NSString stringWithCString:(char *)value encoding:NSUTF8StringEncoding] forKey:[NSString stringWithCString:(char *)attribute->name encoding:NSUTF8StringEncoding]]; xmlFree(value); attribute = attribute->next; } [itemDict setObject:attrDict forKey:@"attr"]; [attrDict release]; /*   */ value = xmlNodeGetContent(node); [itemDict setObject:[NSString stringWithCString:(char*)value encoding:NSUTF8StringEncoding] forKey:@"value"]; xmlFree(value); /*   */ NSMutableArray *childArray = [[NSMutableArray alloc] initWithCapacity:1]; xmlNode *child = NULL; for (child = node->children; child != NULL; child = child->next) { NSDictionary *childDict = [self getNodeInfo:child]; if ([childDict count]) { [childArray addObject:childDict]; } } xmlFree(child); if ([childArray count]) [itemDict setObject:childArray forKey:@"child"]; [childArray release]; } return (NSDictionary *)itemDict; } 
      





/* xml */ - (NSDictionary *)xmlToDict { NSDictionary *resultDict = [NSDictionary dictionary]; if (self.content != nil) { xmlDocPtr doc = xmlParseMemory([self.content bytes], [self.content length]); if (!doc) { // NSLog(@"error"); } else { xmlNode *root = NULL; root = xmlDocGetRootElement(doc); resultDict = [NSDictionary dictionaryWithDictionary:[self getNodeInfo:root]]; xmlFree(root); } } return resultDict; } /* xml , */ -(NSDictionary *)getNodeInfo:(xmlNode *)node { NSMutableDictionary *itemDict = [[[NSMutableDictionary alloc] initWithCapacity:1] autorelease]; xmlChar *value = NULL; xmlAttr *attribute = NULL; if (node && node->name && ![[NSString stringWithCString:(char *)node->name encoding:NSUTF8StringEncoding] isEqualToString:@"text"]) { /* */ value = (xmlChar*)node->name; [itemDict setObject:[NSString stringWithCString:(char *)value encoding:NSUTF8StringEncoding] forKey:@"name"]; xmlFree(value); /* */ attribute = node->properties; NSMutableDictionary *attrDict = [[NSMutableDictionary alloc] initWithCapacity:1]; while(attribute && attribute->name && attribute->children) { value = xmlNodeListGetString(node->doc, attribute->children, 1); [attrDict setObject:[NSString stringWithCString:(char *)value encoding:NSUTF8StringEncoding] forKey:[NSString stringWithCString:(char *)attribute->name encoding:NSUTF8StringEncoding]]; xmlFree(value); attribute = attribute->next; } [itemDict setObject:attrDict forKey:@"attr"]; [attrDict release]; /* */ value = xmlNodeGetContent(node); [itemDict setObject:[NSString stringWithCString:(char*)value encoding:NSUTF8StringEncoding] forKey:@"value"]; xmlFree(value); /* */ NSMutableArray *childArray = [[NSMutableArray alloc] initWithCapacity:1]; xmlNode *child = NULL; for (child = node->children; child != NULL; child = child->next) { NSDictionary *childDict = [self getNodeInfo:child]; if ([childDict count]) { [childArray addObject:childDict]; } } xmlFree(child); if ([childArray count]) [itemDict setObject:childArray forKey:@"child"]; [childArray release]; } return (NSDictionary *)itemDict; }







NSDataのインターネット(原則的には重要ではない)から取得したxmlをself.contentに格納しています。

xmlにルート要素がない場合、コードを少しやり直して、NSDictionaryの各要素を解析し、NSArrayに「追加」する必要がありますが、結果のこの構造では、控えめに言えば、結果を操作するのは便利ではありません。

私は誰かを助けたことを願っています。そして誰かから批判や提案を聞くかもしれません。

問題があります。libxmlが取るに足らない顔、ほとんどの場合ライブラリ自体の顔を与えます。



All Articles