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
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.
take a look to xpath and this: http://blog.objectgraph.com/index.php/2010/02/24/parsing-html-iphone-development/
in this case the xpath you need is
//category/@name
this with the library mentioned above should return the categories names in a array.
for more xpath syntax, check this: http://www.w3schools.com/xpath/default.asp
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];
}