Created
February 23, 2010 14:10
-
-
Save takuma104/312186 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
NSData+XMLParser | |
Simple XML Parser for iPhone | |
Usage: | |
* -I /usr/include/libxml2 | |
* -L libxml2 | |
Example: | |
NSData *xmlData = [NSData dataWithContentsOfFile: | |
[[NSBundle mainBundle] pathForResource:@"hoge" ofType:@"xml"]]; | |
NSDictonary *root = [xmlData parseAsXML]; | |
NSLog(@"dump: %@", root); | |
NSLog(@"Root node name: %@", [root nodeName]); | |
NSArray *children = [root childArray]; | |
for (NSDictonary *n in children) { | |
NSLog(@"node name:%@ content:%@", [n nodeName], [n nodeContent]); | |
} | |
*/ | |
/////////////////////////////////////////////////////////////////////////////// | |
#import <libxml/tree.h> | |
#import <libxml/parser.h> | |
#import <libxml/HTMLparser.h> | |
#import <libxml/xpath.h> | |
#import <libxml/xpathInternals.h> | |
@interface NSData(XMLParser) | |
- (NSDictionary*)parseAsXML; | |
@end | |
@interface NSDictionary(XMLParser) | |
- (NSString*)nodeName; | |
- (NSString*)nodeContent; | |
- (NSArray*)attributeArray; | |
- (NSArray*)childArray; | |
- (NSString*)attributeContentByName:(NSString*)attributeName; | |
- (NSDictionary*)childNodeByNodeName:(NSString*)nodeName; | |
@end | |
@interface NSArray(XMLParser) | |
- (NSString*)attributeContentByName:(NSString*)attributeName; | |
- (NSDictionary*)childNodeByNodeName:(NSString*)nodeName; | |
@end | |
/////////////////////////////////////////////////////////////////////////////// | |
@implementation NSDictionary(XMLParser) | |
- (NSString*)nodeName { | |
return [self valueForKey:@"nodeName"]; | |
} | |
- (NSString*)nodeContent { | |
return [self valueForKey:@"nodeContent"]; | |
} | |
- (NSArray*)attributeArray { | |
return [self valueForKey:@"nodeAttributeArray"]; | |
} | |
- (NSArray*)childArray { | |
return [self valueForKey:@"nodeChildArray"]; | |
} | |
- (NSString*)attributeContentByName:(NSString*)attributeName { | |
return [[self attributeArray] attributeContentByName:attributeName]; | |
} | |
- (NSDictionary*)childNodeByNodeName:(NSString*)nodeName { | |
return [[self childArray] childNodeByNodeName:nodeName]; | |
} | |
@end | |
@implementation NSArray(XMLParser) | |
- (NSString*)attributeContentByName:(NSString*)attributeName { | |
for (NSDictionary *d in self) { | |
if ([[d valueForKey:@"attributeName"] isEqualToString:attributeName]) { | |
return [d valueForKey:@"nodeContent"]; | |
} | |
} | |
return nil; | |
} | |
- (NSDictionary*)childNodeByNodeName:(NSString*)nodeName { | |
for (NSDictionary *d in self) { | |
if ([[d nodeName] isEqualToString:nodeName]) { | |
return d; | |
} | |
} | |
return nil; | |
} | |
@end | |
@implementation NSData(XMLParser) | |
// original code by Matt Gallagher | |
// http://cocoawithlove.com/2008/10/using-libxml2-for-parsing-and-xpath.html | |
static NSDictionary *DictionaryForNode(xmlNodePtr currentNode, NSMutableDictionary *parentResult) | |
{ | |
NSMutableDictionary *resultForNode = [NSMutableDictionary dictionary]; | |
if (currentNode->name) | |
{ | |
NSString *currentNodeContent = | |
[NSString stringWithCString:(const char *)currentNode->name encoding:NSUTF8StringEncoding]; | |
[resultForNode setObject:currentNodeContent forKey:@"nodeName"]; | |
} | |
if (currentNode->content && currentNode->type != XML_DOCUMENT_TYPE_NODE) | |
{ | |
NSString *currentNodeContent = | |
[NSString stringWithCString:(const char *)currentNode->content encoding:NSUTF8StringEncoding]; | |
if ([[resultForNode objectForKey:@"nodeName"] isEqual:@"text"] && parentResult) | |
{ | |
currentNodeContent = [currentNodeContent | |
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; | |
NSString *existingContent = [parentResult objectForKey:@"nodeContent"]; | |
NSString *newContent; | |
if (existingContent) | |
{ | |
newContent = [existingContent stringByAppendingString:currentNodeContent]; | |
} | |
else | |
{ | |
newContent = currentNodeContent; | |
} | |
[parentResult setObject:newContent forKey:@"nodeContent"]; | |
return nil; | |
} | |
[resultForNode setObject:currentNodeContent forKey:@"nodeContent"]; | |
} | |
xmlAttr *attribute = currentNode->properties; | |
if (attribute) | |
{ | |
NSMutableArray *attributeArray = [NSMutableArray array]; | |
while (attribute) | |
{ | |
NSMutableDictionary *attributeDictionary = [NSMutableDictionary dictionary]; | |
NSString *attributeName = | |
[NSString stringWithCString:(const char *)attribute->name encoding:NSUTF8StringEncoding]; | |
if (attributeName) | |
{ | |
[attributeDictionary setObject:attributeName forKey:@"attributeName"]; | |
} | |
if (attribute->children) | |
{ | |
NSDictionary *childDictionary = DictionaryForNode(attribute->children, attributeDictionary); | |
if (childDictionary) | |
{ | |
[attributeDictionary setObject:childDictionary forKey:@"attributeContent"]; | |
} | |
} | |
if ([attributeDictionary count] > 0) | |
{ | |
[attributeArray addObject:attributeDictionary]; | |
} | |
attribute = attribute->next; | |
} | |
if ([attributeArray count] > 0) | |
{ | |
[resultForNode setObject:attributeArray forKey:@"nodeAttributeArray"]; | |
} | |
} | |
xmlNodePtr childNode = currentNode->children; | |
if (childNode) | |
{ | |
NSMutableArray *childContentArray = [NSMutableArray array]; | |
while (childNode) | |
{ | |
NSDictionary *childDictionary = DictionaryForNode(childNode, resultForNode); | |
if (childDictionary) | |
{ | |
[childContentArray addObject:childDictionary]; | |
} | |
childNode = childNode->next; | |
} | |
if ([childContentArray count] > 0) | |
{ | |
[resultForNode setObject:childContentArray forKey:@"nodeChildArray"]; | |
} | |
} | |
return resultForNode; | |
} | |
- (NSDictionary*)parseAsXML { | |
xmlDocPtr doc = xmlReadMemory([self bytes], | |
[self length], | |
"", | |
NULL, | |
XML_PARSE_RECOVER); | |
if (doc == NULL) { | |
NSLog(@"Unable to parse."); | |
return nil; | |
} | |
NSDictionary *res = DictionaryForNode(xmlDocGetRootElement(doc), nil); | |
xmlFreeDoc(doc); | |
return res; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment