Created
March 15, 2012 11:24
-
-
Save jeffkreeftmeijer/2043748 to your computer and use it in GitHub Desktop.
Objective-C XML parser
This file contains hidden or 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
#import <Foundation/Foundation.h> | |
@interface XmlParser : NSObject <NSXMLParserDelegate> | |
@property (strong, nonatomic) NSData *xmlData; | |
@property (strong, nonatomic) NSMutableDictionary *dictionary; | |
@property (strong, nonatomic) NSMutableDictionary *currentNode; | |
@property (strong, nonatomic) NSMutableDictionary *currentParentNode; | |
- (id)initWithXMLData:(NSData *)xmlData; | |
- (NSMutableDictionary *)dictionary; | |
@end |
This file contains hidden or 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
#import "XmlParser.h" | |
@implementation XmlParser | |
@synthesize xmlData = _xmlData, dictionary = _dictionary, currentNode = _currentNode, currentParentNode = _currentParentNode; | |
- (id)initWithXMLData:(NSData *)xmlData | |
{ | |
if(self = [super init]){ | |
_xmlData = xmlData; | |
} | |
return self; | |
} | |
- (NSMutableDictionary *)dictionary | |
{ | |
if(!_dictionary){ | |
_dictionary = [[NSMutableDictionary alloc] init]; | |
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:self.xmlData]; | |
parser.delegate = self; | |
[parser parse]; | |
} | |
return _dictionary; | |
} | |
- (NSMutableDictionary *)currentNode | |
{ | |
if(!_currentNode){ | |
_currentNode = _dictionary; | |
} | |
return _currentNode; | |
} | |
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict | |
{ | |
NSMutableDictionary *node = [[NSMutableDictionary alloc] init]; | |
[self.currentNode setObject:node forKey:elementName]; | |
self.currentParentNode = self.currentNode; | |
self.currentNode = node; | |
if([attributeDict count] != 0) | |
{ | |
[self.currentNode setObject:attributeDict forKey:@"attributes"]; | |
} | |
} | |
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName | |
{ | |
self.currentNode = self.currentParentNode; | |
} | |
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string | |
{ | |
NSString *trimmedString = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; | |
if([trimmedString length] != 0){ | |
[self.currentNode setObject:trimmedString forKey:@"value"]; | |
} | |
} | |
@end |
...and then there's the problem with this fragment:
<parent><child>A</child><child>B</child></parent>
Subnodes with the same name collide in the dictionary, and the last subnode is the only one represented in the final structure. This is what we get for the above fragment:
parent {
child {
value {
B
}
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There are a number of problems with this code. The most significant is the use of the "currentNode" and "currentParentNode" method of keeping track of the XML tree. Two nodes means you can only have an XML document with a single level of node nesting before you lose track of where you are and both nodes point to each other.
To fix it, replace the "currentParentNode" with a stack.