Search code examples
iosobjective-cuitableviewrssnsxmlparser

NSXMLParser adding two elements to one TableView cell


I'm trying to use NSXMLParser to populate a UITableView with titles of articles from several separate RSS feeds:

for (NSString* feedString in [[NSUserDefaults standardUserDefaults] objectForKey:@"RSSFeeds"])
{
    NSURL *url = [NSURL URLWithString:feedString];
    parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
    [parser setDelegate:self];
    [parser setShouldResolveExternalEntities:NO];
    [parser parse];
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{    
    element = elementName;

    if ([element isEqualToString:@"item"])
    {        
     item    = [[NSMutableDictionary alloc] init];
     title   = [[NSMutableString alloc] init];
     link    = [[NSMutableString alloc] init];
    }
}

This seems to work well if there is only one RSS feed but as soon as there is more than one, the first title from the second feed is appended to the the last title from the first feed and they share the same cell in the table view.

I think this method is at the heart of the problem but am struggling to get it to work properly:

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if ([element isEqualToString:@"title"])
    {
        [title appendString:string];
    }

    else if ([element isEqualToString:@"link"])
    {
        [link appendString:string];
    }
}

I appreciate I'm probably overlooking something obvious but any pointers would be appreciated.

My didEnd code:

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{    
  if ([elementName isEqualToString:@"item"])
  {
    [item setObject:title forKey:@"title"];
    [item setObject:link forKey:@"link"];
    [feeds addObject:[item copy]];
  }
}

- (void)parserDidEndDocument:(NSXMLParser *)parser
{    
    [self.tableView reloadData];
}

Solution

  • NOTE: not the most optimized solution but should work (i'll edit this later)

    for (NSString* feedString in [[NSUserDefaults standardUserDefaults] objectForKey:@"RSSFeeds"])
    {
        NSURL *url = [NSURL URLWithString:feedString];
        parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
        [parser setDelegate:self];
        [parser setShouldResolveExternalEntities:NO];
        [parser parse];
    
        //declare "NSMutableString *strCurrent;" in the .h of this class
        strCurrent = [NSMutableString alloc] init];
    }
    

    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
    {
        [strCurrent appendString:string];
    }
    

    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
                                            namespaceURI:(NSString *)namespaceURI
                                           qualifiedName:(NSString *)qName
                                              attributes:(NSDictionary *)attributeDict
    {    
        if ([elementName isEqualToString:@"item"]) {
            item = [[NSMutableDictionary alloc] init];
        }
    
        if ([elementName isEqualToString:@"title"]) {        
            strCurrent = [[NSMutableString alloc] init];
        }
    
        if ([elementName isEqualToString:@"link"]) {        
            strCurrent = [[NSMutableString alloc] init];
        }
    }
    

    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
                                          namespaceURI:(NSString *)namespaceURI
                                         qualifiedName:(NSString *)qName
    {    
        if ([elementName isEqualToString:@"title"]) {
            [item setObject:strCurrent forKey:@"title"];
        }
    
        if ([elementName isEqualToString:@"link"]) {
            [item setObject:strCurrent forKey:@"link"];
        }
    
        if ([elementName isEqualToString:@"item"]) {
            [feeds addObject:[item copy]];
        }
    }