You need
an array to keep track of all of your modes, e.g.
modesArray
;a dictionary of object to keep track of you're modes'
ChannelCount
andName
, e.g.modeDictionary
; andand some
BOOL
variable so you know if you're parsing your array of modes or not (most importantly, so you can distinguish betweenName
in aMode
and the higher-levelName
, e.g.parsingModes
.
You can then,
When you start a Modes, initialize your array;
When you start a
Mode
, initialize the dictionary;When you complete a
Name
orChannelCount
, update the mode dictionary;When you complete a
Mode
, you can concatenate these two values into a single string, and add that string to your array;When you complete the
Modes
, you can join all of those strings in theMode
array with a newline.
Thus yielding something like:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"Fixture"])
{
currentFixture = [[Fixture alloc] init];
}
else if ([elementName isEqualToString:@"Modes"])
{
modesArray = [NSMutableArray array];
parsingModes = YES;
}
else if ([elementName isEqualToString:@"Mode"])
{
modeDictionary = [NSMutableDictionary dictionary];
}
else
{
currentNodeContent = [NSMutableString string];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
[currentNodeContent appendString:string];
}
-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (parsingModes)
{
if ([elementName isEqualToString:@"Name"]) {
modeDictionary[@"Name"] = currentNodeContent;
}
else if ([elementName isEqualToString:@"ChannelCount"]) {
modeDictionary[@"ChannelCount"] = currentNodeContent;
}
else if ([elementName isEqualToString:@"Mode"]) {
[modesArray addObject:[NSString stringWithFormat:@"%@ %@", modeDictionary[@"ChannelCount"], modeDictionary[@"Name"]]];
modeDictionary = nil;
}
else if ([elementName isEqualToString:@"Modes"]) {
currentFixture.longStringWithModes = [modesArray componentsJoinedByString:@"\n"];
modesArray = nil;
parsingModes = NO;
}
}
else
{
if ([elementName isEqualToString:@"Name"]) {
currentFixture.title = currentNodeContent;
}
}
// carry on with your other elements
currentNodeContent = nil;
}
(Note I shifted to camelCase.)
Having shown you how to do this, I'd advise against it. It's better for the database to keep the data in separate fields. This concatenating everything into a single string might be something you do in the UI, but the database should probably reflect the underlying data structure. Having said that, since you have multiple Mode
entries for each fixture, that means that you'd probably have a separate table for those.