Convert XML to NSDictionary in iOS

Post date: Apr 25, 2014 6:57:03 AM

Here is my most reusable code. I have used this code all my project to parse xml. 

This class helps you to parse the XML using NSXMLParser and gives NSDictionary as an output.

CXMLParser.h

#import <Foundation/Foundation.h>

@protocol ParserXMLDelegate

@required

- (NSMutableArray*)parseData:(NSDictionary*)data;

@end

@interface CXMLParser : NSObject<NSXMLParserDelegate>

{

    NSMutableArray *dictionaryStack;

    NSMutableString *textInProgress;

    NSError * __strong *errorPointer;

}

+ (NSDictionary *)dictionaryForXMLData:(NSData *)data error:(NSError **)errorPointer;

+ (NSDictionary *)dictionaryForXMLString:(NSString *)string error:(NSError **)errorPointer;

@end

CXMLParser.m

#import "CXMLParser.h"

NSString *const kXMLReaderTextNodeKey = @"text";

@interface CXMLParser (Internal)

- (id)initWithError:(NSError **)error;

- (NSDictionary *)initializeWithData:(NSData *)data;

@end

@implementation CXMLParser

#pragma mark -

#pragma mark Public methods

+ (NSDictionary *)dictionaryForXMLData:(NSData *)data error:(NSError **)error

{

    CXMLParser *reader = [[CXMLParser alloc] initWithError:error];

    NSDictionary *rootDictionary = [reader initializeWithData:data];

    return rootDictionary;

}

+ (NSDictionary *)dictionaryForXMLString:(NSString *)string error:(NSError **)error

{

    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

    return [CXMLParser dictionaryForXMLData:data error:error];

}

#pragma mark -

#pragma mark Parsing

- (id)initWithError:(NSError * __strong*)error

{

    if (self = [super init])

    {

        errorPointer = error;

    }

    return self;

}

- (NSDictionary *)initializeWithData:(NSData *)data

{

    // Clear out any old data

    

    dictionaryStack = [[NSMutableArray alloc] init];

    textInProgress = [[NSMutableString alloc] init];

    

    // Initialize the stack with a fresh dictionary

    [dictionaryStack addObject:[NSMutableDictionary dictionary]];

    

    // Parse the XML

    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];

    parser.delegate = self;

    BOOL success = [parser parse];

    

    // Return the stack's root dictionary on success

    if (success)

    {

        NSDictionary *resultDict = [dictionaryStack objectAtIndex:0];

        return resultDict;

    }

    return nil;

}

#pragma mark -

#pragma mark NSXMLParserDelegate methods

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict

{

    // Get the dictionary for the current level in the stack

    NSMutableDictionary *parentDict = [dictionaryStack lastObject];

    // Create the child dictionary for the new element, and initilaize it with the attributes

    NSMutableDictionary *childDict = [NSMutableDictionary dictionary];

    [childDict addEntriesFromDictionary:attributeDict];

    

    // If there's already an item for this key, it means we need to create an array

    id existingValue = [parentDict objectForKey:elementName];

    if (existingValue)

    {

        NSMutableArray *array = nil;

        if ([existingValue isKindOfClass:[NSMutableArray class]])

        {

            // The array exists, so use it

            array = (NSMutableArray *) existingValue;

        }

        else

        {

            // Create an array if it doesn't exist

            array = [NSMutableArray array];

            [array addObject:existingValue];

            // Replace the child dictionary with an array of children dictionaries

            [parentDict setObject:array forKey:elementName];

        }

        

        // Add the new child dictionary to the array

        [array addObject:childDict];

    }

    else

    {

        // No existing value, so update the dictionary

        [parentDict setObject:childDict forKey:elementName];

    }

    

    // Update the stack

    [dictionaryStack addObject:childDict];

}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName

{

    // Update the parent dict with text info

    NSMutableDictionary *dictInProgress = [dictionaryStack lastObject];

    

    // Set the text property

    if ([textInProgress length] > 0)

    {

        [dictInProgress setObject:textInProgress forKey:kXMLReaderTextNodeKey];

        // Reset the text

        textInProgress = [[NSMutableString alloc] init];

    }

    

    // Pop the current dict

    [dictionaryStack removeLastObject];

}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

{

    // Build the text value

    [textInProgress appendString:string];

}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError

{

    // Set the error pointer to the parser's error object

    *errorPointer = parseError;

}

@end

Code snapshot to use this class

   NSString* strXML= [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"xml"];

    NSData* data=[NSData dataWithContentsOfFile:strXML];

    NSDictionary* dictionary =[CXMLParser dictionaryForXMLData:data error:nil];

You can download this files here

https://sites.google.com/site/greateindiaclub/downloads/file-cabinet/CXMLParser.h

https://sites.google.com/site/greateindiaclub/downloads/file-cabinet/CXMLParser.m

github link is here

https://github.com/boobalaninfo/iOS-XMLParser