usingsystem8 usingsystem8 - 2 months ago 15
iOS Question

How to load data from plist without changing the order

I want to load NSDictionary from the following plist file, without changing the order of it.
Plist file

This plist file is Here.

I have researched many things, and I found OrderedDictionary and M13OrderedDictionary.

First, I tried NSDictionary (I know it fails)

- (void)testNSDictionary {
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSLog(@"%@",dictionary);
}


Then I got the following log:

{
G = {
R = {
H = "";
S = "";
};
V = {
T = "";
};
};
S = {
B = {
L = "";
};
O = {
K = "";
L = "";
};
V = {
T = "";
};
};
}


This is completely different order from the original plist file! (I know)

I think this is alphabetical order.

Next, I tried OrderedDictionary with the following code:

#import "OrderedDictionary.h"
- (void)testOrderedDictionary {
OrderedDictionary *dictionary = [OrderedDictionary dictionaryWithContentsOfFile:filePath];
NSLog(@"%@",dictionary);
}


Then I got the following log:

{
G = {
R = {
H = "";
S = "";
};
V = {
T = "";
};
};
S = {
B = {
L = "";
};
O = {
K = "";
L = "";
};
V = {
T = "";
};
};
}


Huh? This is the same result as NSDictionary.

Finally, I tried M13OrderedDictionary with the following code.

#import "M13OrderedDictionary.h"
- (void)testM13OrderedDictionary {
M13OrderedDictionary *dictionary = [M13OrderedDictionary orderedDictionaryWithContentsOfFile:filePath];
NSLog(@"%@",dictionary);
}


Then I got the following log:

{
}


Nothing returned. I don't understand what is going on.

I would like to know how I can correctly use OrderedDictionary and M13OrderedDictionary. If they are outdated, I want to know the alternative way to parse plist file into NSDictionary or NSArray or something.



Note: I don't want to change plist file, because this format is the best for me.

Answer

Finally I succeeded in parsing my plist file using OrderedDictionary. This is my code:

[ParserDelegate.h]

@interface ParserDelegate : NSObject<NSXMLParserDelegate>
@end

[ParserDelegate.m]

#import "ParserDelegate.h"
#import "OrderedDictionary.h"
@interface ParserDelegate()
@end

@implementation ParserDelegate {
    BOOL isDict;
    BOOL isKey;
    BOOL isString;
    BOOL stringExists;
    int layer;
    int arrayNum;
    MutableOrderedDictionary *parsedDictionary;
    MutableOrderedDictionary *tempDictionary;
    MutableOrderedDictionary *tempTempDictionary;
    NSMutableArray *keysArray;
}

- (void)parserDidStartDocument:(NSXMLParser *)parser {
    NSLog(@"Started parsing plist file...");
    isKey = NO;
    layer = 0;
    arrayNum = 0;
    parsedDictionary = [[MutableOrderedDictionary alloc] init];
    tempDictionary = [[MutableOrderedDictionary alloc] init];
    tempTempDictionary = [[MutableOrderedDictionary alloc] init];
    keysArray = [NSMutableArray array];
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    if ([elementName isEqualToString:@"dict"]) {
        isDict = YES;
        layer++;
    } else if ([elementName isEqualToString:@"key"]) {
        isKey = YES;
    } else if ([elementName isEqualToString:@"string"]) {
        isString = YES;
        stringExists = NO;
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if (isDict) {
        if ([tempDictionary count] != 0) {
            [tempDictionary removeAllObjects];
        }
        isDict = NO;
    }
    if (isKey) {
        [keysArray addObject:string];
        arrayNum++;
    }
    if (isString) {
        tempDictionary[[keysArray objectAtIndex:[keysArray count] - 1]] = string;
        stringExists = YES;
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    if ([elementName isEqualToString:@"dict"]) {
        layer--;
        if (layer == 2) {
            tempTempDictionary[[keysArray objectAtIndex:[keysArray count] - [tempDictionary count] - 1]] = [tempDictionary copy];
        } else if (layer == 1) {
            parsedDictionary[[keysArray objectAtIndex:[keysArray count] - arrayNum]] = [tempTempDictionary copy];
            [tempTempDictionary removeAllObjects];
            arrayNum = 0;
        }
    } else if ([elementName isEqualToString:@"key"]) {
        isKey = NO;
    } else if ([elementName isEqualToString:@"string"]) {
        if (!stringExists) {
            tempDictionary[[keysArray objectAtIndex:[keysArray count] - 1]] = @"";
        }
        isString = NO;
    }
}

-(void)parserDidEndDocument:(NSXMLParser *)parser {
    NSLog(@"Finished parsing!");
    NSLog(@"%@",[parsedDictionary description]);
}

@end

I'm sorry that this script supports only my plist file, so other format plist files can't be parsed by this.

Usage:

ParserDelegate *parserDelegate = [[ParserDelegate alloc] init];
NSURL *url = [NSURL fileURLWithPath:filePath];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
parser.delegate = parserDelegate;
[parser parse];