Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

MACloop

macrumors 6502
Original poster
May 18, 2009
393
0
Germany
Hello all and happy new year to start with!

I have a question regadring the parsing of an XML file.
I have an application whicht uses the parsing code below. Everything works all right if I run the code below. The problem is that I have an update function in my app, meaning the user may re-parse the xml file as many times he wants during the program-run. If I release the current-element-variable as in the code below, the app crashes. I use the same parser object as I did the first time and I load the data with NSURLConnection- i.e when the connection is ready is the parser next to do his work.

Why can I not release the object as I do in my code?
It must be a huge memory leak if I do not release this object or did I miss something here?

And, is it all right to release the currentNodeContent variable when the parser is done?

I hope someone has some good advice? or ideas?
Thanks in advance,
MACloop

Code:
#pragma mark -
#pragma mark Parser Delegate Methods

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
	currentNodeContent = [[NSMutableString alloc] init];//
	if([elementName isEqualToString:@"StartTag"]) {//a new item
		currentElement = [[CurrentElement alloc]init];//allocting 
	}
	if([elementName isEqualToString:@"Data"]){
		nameString = [attributeDict objectForKey:@"name"];
	} 
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
	if([elementName isEqualToString:@"number"]) {
		[currentElement setValue:currentNodeContent forKey:@"number"];
	}
	if([elementName isEqualToString:@"description"]) {
		[currentElement setValue:currentNodeContent forKey:@"description"];
	}
	
	if([elementName isEqualToString:@"Data"]) {
		if([nameString isEqualToString:@"street"]) {
			[currentElement setValue:currentNodeContent forKey:@"street"];
		}
		if([nameString isEqualToString:@"town"]){
			[currentElement setValue:currentNodeContent forKey:@"town"];
		}
		if([nameString isEqualToString:@"mail"]){
			[currentElement setValue:currentNodeContent forKey:@"mail"];
		}
	}
	if([elementName isEqualToString:@"StartTag"]) {
		[arrayWithAllObjects addObject:currentElement];
		[currentElement release];
	}
	
	else
		return;
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
	[currentNodeContent appendString:[string stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]]];
}

- (void)parserDidEndDocument:(NSXMLParser *)parser {
	[currentNodeContent release];
	
//doing the rest here...

}

- (void)parser:(NSXMLParser *)p parseErrorOccurred:(NSError *)parseError {
	[p abortParsing];
	parserProblems = TRUE;
	UIAlertView *alert = [[[UIAlertView alloc]initWithTitle:@"Error" message:@"Problems" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]autorelease];
	[alert show];
}
 

MACloop

macrumors 6502
Original poster
May 18, 2009
393
0
Germany
I think I found a solution. I do not know if it is optimal, but it seem to work and does not look to bad when running the app in "leaks". I did following(new things maked red):

Code:
#pragma mark -
#pragma mark Parser Delegate Methods

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
	currentNodeContent = [[NSMutableString alloc] init];//
	if([elementName isEqualToString:@"StartTag"]) {//a new item
		currentElement = [[CurrentElement alloc]init];//allocting 
	}
	if([elementName isEqualToString:@"Data"]){
		nameString = [attributeDict objectForKey:@"name"];
	} 
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
	if([elementName isEqualToString:@"number"]) {
		[currentElement setValue:currentNodeContent forKey:@"number"];
[COLOR="Red"][currentNodeContent release];
		currentNodeContent = nil;[/COLOR]
	}
	if([elementName isEqualToString:@"description"]) {
		[currentElement setValue:currentNodeContent forKey:@"description"];
[COLOR="Red"][currentNodeContent release];
		currentNodeContent = nil;[/COLOR]
	}
	
	if([elementName isEqualToString:@"Data"]) {
		if([nameString isEqualToString:@"street"]) {
			[currentElement setValue:currentNodeContent forKey:@"street"];
[COLOR="Red"][currentNodeContent release];
		currentNodeContent = nil;[/COLOR]
		}
		if([nameString isEqualToString:@"town"]){
			[currentElement setValue:currentNodeContent forKey:@"town"];
[COLOR="Red"][currentNodeContent release];
		currentNodeContent = nil;[/COLOR]
		}
		if([nameString isEqualToString:@"mail"]){
			[currentElement setValue:currentNodeContent forKey:@"mail"];
[COLOR="Red"][currentNodeContent release];
		currentNodeContent = nil;[/COLOR]
		}
	}
	if([elementName isEqualToString:@"StartTag"]) {
		[arrayWithAllObjects addObject:currentElement];
		[currentElement release];
[COLOR="Red"][currentElement release];[/COLOR]
	}
	
	else
		return;
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
	[currentNodeContent appendString:[string stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]]];
}

- (void)parserDidEndDocument:(NSXMLParser *)parser {
	
//doing the rest here...

}

- (void)parser:(NSXMLParser *)p parseErrorOccurred:(NSError *)parseError {
	[p abortParsing];
	parserProblems = TRUE;
	UIAlertView *alert = [[[UIAlertView alloc]initWithTitle:@"Error" message:@"Problems" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]autorelease];
	[alert show];
}

So how does this solution look? Is it the way to solve this problem? And why do you have to write currentElement = nil after the release?

Another parsing question is the one when a parser fails. I have used the delegate method above - is that corrent? I have tried to provoke a failure in order to get this method called as I let the parser read data from a wrong formed document. By wrong formed I mean a document with other tags than the one the parser is looking for. But that did not lead to the method being called - why?

Thanks in advance
MACloop
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.