How to display image from a RSS feed

2019-05-24 06:36发布

问题:

I'm trying to build an app that shows the latest RSS feeds from http://news.yahoo.com/rss/ I'm able to parse the xml using NSXMLParserDelegate, I'm able to show the date and time along with the title for the particular feed, but I also want to display an image for every feed, I know how to parse the main elements but I dont know how to pass the attributes for a child element which has a url as its key... e.g. the above feed consists of the following:

<item>
  <title>fooo</title>
  <description ahref="some link" image src="http://l1.yimg.com/bt/api/res/1.2/Wo3_apH.kz7DMvOj7MDtRQ--/YXBwaWQ9eW5ld3M7Zmk9ZmlsbDtoPTg2O3E9ODU7dz0xMzA-/http://media.zenfs.com/en_us/News/ap_webfeeds/20c464ff99815420210f6a706700a792.jpg"
     </description>

I need the image from the IMG SRC in my tableview along with the title and date for that particular feed. I'm confused as to how to parse the IMG SRC attribute and add it to my tableview with altered size so that it doesnt disrupt my title and date.

What I have done so far:

viewDidAppear

-(void)viewDidAppear:(BOOL)animated
 {
     if ([stories count] == 0) 
     {
         NSString * path = @"http://news.yahoo.com/rss/";
         [self parseXMLFileAtURL:path];
     }
     cellSize = CGSizeMake([newsTable bounds].size.width, 80);
 }

-(void)parseXMLFileAtURL:(NSString *)URL

- (void)parseXMLFileAtURL:(NSString *)URL
{
    stories = [[NSMutableArray alloc] init];

    //you must then convert the path to a proper NSURL or it won't work
    NSURL *xmlURL = [NSURL URLWithString:URL];

    // here, for some reason you have to use NSClassFromString when trying to alloc NSXMLParser, otherwise you will get an object not found error
    // this may be necessary only for the toolchain
    rssParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];

    // Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks.
    [rssParser setDelegate:self];

    // Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser.
    [rssParser setShouldProcessNamespaces:NO];
    [rssParser setShouldReportNamespacePrefixes:NO];
    [rssParser setShouldResolveExternalEntities:NO];
    [rssParser parse];
}

didStartElement

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
    //NSLog(@"found this element: %@", elementName);
    currentElement = [elementName copy];

    if ([elementName isEqualToString:@"item"]) {
        // clear out our story item caches...
        item = [[NSMutableDictionary alloc] init];
        currentTitle = [[NSMutableString alloc] init];
        currentDate = [[NSMutableString alloc] init];
        currentSummary = [[NSMutableString alloc] init];
        currentLink = [[NSMutableString alloc] init];
    }
}

foundCharacters

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    //NSLog(@"found characters: %@", string);
    // save the characters for the current item...
    if ([currentElement isEqualToString:@"title"]) {
        [currentTitle appendString:string];
    } else if ([currentElement isEqualToString:@"link"]) {
        [currentLink appendString:string];
    } else if ([currentElement isEqualToString:@"description"]) {
        [currentSummary appendString:string];
    } else if ([currentElement isEqualToString:@"pubDate"]) {
        [currentDate appendString:string];
    }
}

didEndElement

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    //NSLog(@"ended element: %@", elementName);
    if ([elementName isEqualToString:@"item"]) {
        // save values to an item, then store that item into the array...
        [item setObject:currentTitle forKey:@"title"];
        [item setObject:currentLink forKey:@"link"];
        [item setObject:currentSummary forKey:@"summary"];
        [item setObject:currentDate forKey:@"pubDate"];
    }
}

didEndDocument

- (void)parserDidEndDocument:(NSXMLParser *)parser 
{
    [newsTable reloadData];
}

numberOfRows and cellForRowAtIndexPath

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [stories count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellIdentifier = @"cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier] autorelease];
    }

    int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
    cell.textLabel.text=[[stories objectAtIndex: storyIndex] objectForKey: @"title"];
    cell.detailTextLabel.text=[[stories objectAtIndex:storyIndex] objectForKey:@"pubDate"];

    cell.textLabel.font=[UIFont fontWithName:@"Arial" size:12];
    cell.textLabel.numberOfLines = 0;
    cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;

    return cell;
}

How do I get the image on the right hand side of the cell?

回答1:

In answer to the question in the title, to load an image, you parse the RSS feed for the URL of the string using NSXMLParser object, and when you want to present that image to the user, you use that URL to retrieve the image into a NSData, create a UIImage for that, and then set the image property of the UIImageView accordingly. See the cellForRowAtIndexPath in the listing below.

In terms of the specifics of the implementation, I've significantly revised this answer on the basis of the fact that you're reading a feed from http://news.yahoo.com/rss/ which has a format significantly different than what you show in your example XML listing. The format actually appears to be:

<item>
  <title>Palestinian death toll ...</title>
  <description>this contains the html version of the story description</description>
  <link>http://news.yahoo.com/palestinian-death-toll-...</link>
  <pubDate>Mon, 19 Nov 2012 11:20:15 -0500</pubDate>
  <source url="http://www.reuters.com/">Reuters</source>
  <guid isPermaLink="false">palestinian-death-toll-...</guid>
  <media:content url="http://the.url.for.image/images/palestinian.JPG" type="image/jpeg" width="130" height="86"></media:content>
  <media:text type="html">another html version of the text</media:text>
  <media:credit role="publishing company"></media:credit>
</item>

Some of this is just standard XML tags title, description, etc. where you're grabbing values between the open and close tags (for which you can just use NSXMLParserDelegate method parser:foundCharacters:). But the image URL is actually inside the url attribute of the media:content tag, itself, in which case you have to use the NSXMLParserDelegate method didStartElement and inquire on the attributes parameter.

So, given that, I've uploaded a sample Yahoo News reader which demonstrates the process of parsing the Yahoo RSS feed. Note, this is a fairly primitive implementation, but hopefully this gives you the basic idea.