Search code examples
xmliosnsarraynsdictionarynsxmlparser

Parse XML item "Category" into an NSArray with NSDictionary


Question:

The generated XML file from an .XSD template produces the output pasted below. Since category's keys are image, my standard way of parsing the image items wont work on category. I would like to place the category name="Category #" into an array, How can I make an array from the category fields.

What I need:

What I want is an array of dictionaries. Each position contains a dictionary representing one category, and each dictionary contains images for that category.

Array: @"Category 1",@"Category 2",@"Category 3";

For each Array, a Dictionary with: <image> and everything in between </image>

Basically, I need to create a plist like the following image, from the XML data source

enter image description here

XML Output:

<?xml version="1.0" encoding="UTF-8"?>
<app xmlns="http://www.wrightscs.com/_xml_.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.wrightscs.com/_xml_.xsd" name="Testing" unlock_product_id="com.wrightscs.all">
    <bannerImg>http://www.wrightscs.com</bannerImg> 
    <category name="Category 1" icon="http://www.wrightscs.com">
        <image>
                <title>title</title>
                <thumbUrl>http://www.wrightscs.com</thumbUrl>
                <sampleUrl>http://www.wrightscs.com</sampleUrl>
                <imageUrl>http://www.wrightscs.com</imageUrl>
                <description>These items / keys not an issue.</description>
                <infoUrl>http://www.wrightscs.com</infoUrl>
                <license>http://www.wrightscs.com</license>
                <licenseUrl>http://www.wrightscs.com</licenseUrl>
        </image>
    </category>
    <category name="Category 2" icon="http://www.wrightscs.com">
        <image>
                <title>title</title>
                <thumbUrl>http://www.wrightscs.com</thumbUrl>
                <sampleUrl>http://www.wrightscs.com</sampleUrl>
                <imageUrl>http://www.wrightscs.com</imageUrl>
                <description>These items / keys not an issue.</description>
                <infoUrl>http://www.wrightscs.com</infoUrl>
                <license>http://www.wrightscs.com</license>
                <licenseUrl>http://www.wrightscs.com</licenseUrl>
        </image>
    </category> 
    <category name="Category 3" icon="http://www.wrightscs.com">
        <image>
                <title>title</title>
                <thumbUrl>http://www.wrightscs.com</thumbUrl>
                <sampleUrl>http://www.wrightscs.com</sampleUrl>
                <imageUrl>http://www.wrightscs.com</imageUrl>
                <description>These items / keys not an issue.</description>
                <infoUrl>http://www.wrightscs.com</infoUrl>
                <license>http://www.wrightscs.com</license>
                <licenseUrl>http://www.wrightscs.com</licenseUrl>
        </image>
    </category>
</app>

Note: none of the other items / keys are an issue, I am only interested in making category into an array. The URL's in this example are also replaced from the original content.


Solution

  • The Solution:

    #pragma mark -
    #pragma mark Delegate Received
    
    -(void)parsingComplete:(XMLDataSource*)theParser {
        NSArray *categoryArray = [theParser getCategories];
        [categoryArray writeToFile:PLIST atomically:YES];
    }
    - (void)receivedItems:(NSArray *)theItems {
        NSMutableArray *dataItems = [[NSMutableArray alloc] init];
        [dataItems addObjectsFromArray:[NSArray arrayWithContentsOfFile:PLIST]];
    
        NSDictionary * dataItem = [dataItems objectAtIndex:categoryIndex];
        data_ =  [dataItem objectForKey:@"images"];
    
        [[NSNotificationCenter defaultCenter] postNotificationName:@"updateThumbs" object:nil];
    }
    
    
    #pragma mark -
    #pragma mark Parsing Delegates
    
    - (void)parse:(NSData *)data withDelegate:(id)sender onComplete:(SEL)callback 
    {
        parentDelegate = sender;
        onCompleteCallback = callback;
        loading = YES;
    
        NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
        [parser setDelegate:self];
        [parser setShouldProcessNamespaces:NO];
        [parser setShouldReportNamespacePrefixes:NO];
        [parser setShouldResolveExternalEntities:NO];
        [parser parse];
    }
    - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
        parsed = NO;
        loading = NO;
    }
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
    {
        NSString *element = [elementName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        currentElement = element;
        if ([[currentElement lowercaseString] isEqual:@"image"]) {
            inImage = YES;
            itemsDictionary = [[NSMutableDictionary alloc] init];
            [itemsDictionary addEntriesFromDictionary:attributeDict];
        }
    
        if ([[currentElement lowercaseString] isEqual:@"category"]) {
            inCategory = YES;
            categoryDictionary = [[NSMutableDictionary alloc] init];
            [categoryDictionary addEntriesFromDictionary:attributeDict];
        }
    }
    
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qName 
    {
        NSString *element = [elementName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        if ([[element lowercaseString] isEqual:@"image"]) {
            inImage = NO;
            [items addObject:[itemsDictionary copy]];
        }
    
        if ([[element lowercaseString] isEqual:@"category"]) {
            inCategory = NO;
            [categoryDictionary setObject:[items copy] forKey:@"images"];
            [items removeAllObjects];
            [categories addObject:[categoryDictionary copy]];
        }
    }
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 
    {
        NSString *stringValue = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        NSString *element = [currentElement stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    
        /*  skip over blank elements.  */
        if (stringValue == nil || [stringValue isEqual:@""]) {
            return;
        }
    
        if (element != nil && [element length] > 0) {
            if (inImage) {
                if ([itemsDictionary objectForKey:element] != nil) {
                    [itemsDictionary setObject:[NSString stringWithFormat:@"%@%@", [itemsDictionary objectForKey:element], stringValue]
                                        forKey:element];
                } else {
                    [itemsDictionary setObject:stringValue forKey:element];
                }
            } else if ((!inImage) && (inCategory)) {
                if ([categoryDictionary objectForKey:element] != nil) {
                    [categoryDictionary setObject:[NSString stringWithFormat:@"%@%@", [categoryDictionary objectForKey:element], stringValue]
                                           forKey:element];
                } else {
                    [categoryDictionary setObject:stringValue forKey:element];
                }
            } else {
                if ([root objectForKey:element] != nil) {
                    [root setObject:stringValue forKey:element];
                }
            }
        }
    }
    - (void)parserDidStartDocument:(NSXMLParser *)parser {
        NSError * err;
        if(![[NSFileManager defaultManager] fileExistsAtPath:PLIST]) {
            [[NSFileManager defaultManager] removeItemAtPath:PLIST error:&err];
        }
    }
    - (void)parserDidEndDocument:(NSXMLParser *)parser 
    {
        parsed = YES;
        loading = NO;
    
        if ([parentDelegate respondsToSelector:onCompleteCallback]) {
            [parentDelegate performSelector:onCompleteCallback withObject:self];
        }
    
        if ([self respondsToSelector:@selector(receivedItems:)])
            [self receivedItems:items];
        else
            SHOW_ALERT(@"parserDidEndDocument:", @"receivedItems: not responding!", nil, @"Okay", nil)
    }
    
    
    #pragma mark -
    #pragma mark Setters / Getters
    
    - (id)delegate {
        return self;
    }
    - (void)setDelegate:(id)new_delegate {
        _delegate = self;
    }
    - (BOOL)isSuccessful {
        return success;
    }
    - (BOOL)isLoading {
        return loading;
    }
    - (BOOL)isParsed {
        return parsed;
    }
    - (NSArray *)getCategories {
        return categories;
    }
    - (NSDictionary *)getRoot {
        return root;
    }
    - (void)dealloc {
        [super dealloc];
    }