Reputation: 1922
I'm working with RSS feeds in my app, specifically with Drudge Report's. I'm quite new to this sort of stuff, along with being new to using Xcode's NSXMLParser
. Each feed apparently represents an article. Each feed is represented by the <item></item>
tags.
Within these tags, there's a description of info enclosed by the <description></description>
tags. In the description, some articles might have an image associated with that article, as seen in the following screenshot:
The part I highlighted is the image I need to get (specifically, the URL string). I'm able to derive the description each article as an NSMutableString
, but how do I derive the image's URL when I parse the XML with NSXMLParser? The following is my code so far as to how I'm getting all of this done:
@interface ViewController () <NSXMLParserDelegate, UITableViewDataSource, UITableViewDelegate> {
NSXMLParser *parser;
NSMutableArray *feeds;
NSMutableDictionary *item;
NSMutableString *title;
NSMutableString *link;
NSMutableString *description;
NSString *element;
}
.
.(other code)
.
#pragma mark - NSXMLParserDelegate
- (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];
description = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([element isEqualToString:@"title"]) {
[title appendString:string];
}
else if ([element isEqualToString:@"feedburner:origLink"]) {
[link appendString:string];
}
else if ([element isEqualToString:@"description"]) {
[description appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:@"item"]) {
NSString *filteredTitle = [title stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *filteredLink = [link stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (![filteredLink containsString:@"https://itunes.apple.com/"]) {
[item setObject:filteredTitle forKey:@"title"];
[item setObject:filteredLink forKey:@"link"];
[item setObject:description forKey:@"description"];
[feeds addObject:[item copy]];
}
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
[self.tableView reloadData];
}
PROGRESS
So far, I added the following in my didEndElement
method:
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:@"item"]) {
NSString *filteredTitle = [title stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *filteredLink = [link stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (![filteredLink containsString:@"https://itunes.apple.com/"]) {
[item setObject:filteredTitle forKey:@"title"];
[item setObject:filteredLink forKey:@"link"];
[item setObject:description forKey:@"description"];
if ([description rangeOfString:@"img style"].location != NSNotFound)
{
}
[feeds addObject:[item copy]];
}
}
}
Now that I know that the description has the img style
string in it, I need to get the src="whateverImageURL"
. How do I use a regular expression to get the first occurrence of this image URL?
Upvotes: 0
Views: 289
Reputation: 736
you have to implement this protocol
- (void)parser:(NSXMLParser *)parser foundAttributeDeclarationWithName:(NSString *)attributeName forElement:(NSString *)elementName type:(nullable NSString *)type defaultValue:(nullable NSString *)defaultValue;
this allow you to get all attribute for each element found.
Let me know if this help you :)
UPDATE
Here a code that find the url of first img found in a given string
NSString *descriptionString = @"<br><tt><font size=\"3\" color=\"blue\"><b><u>LIST: 10 Worst Winter Storms in Washington History...</u></b></font></tt><br><br><br><font face=\"Arial\" size=\"1\"><i>(Top headline, 3rd story, <a href=\"http://www.nbcwashington.com/news/local/Ten-Worst-Storms-in-DC-History-365815301.html\">link</a>)</i></font><hr style=\"height: 1px; border-style: none; color: #666666; background-color: #666666;\"/><font face=\"Arial\" size=\"2\">Related stories:<div class=\"related-links\" id=\"R:H1:S3\"><a href=\"http://www.wunderground.com/US/DC/001.html#WIN\">BLIZZARD WARNING ISSUED FOR DC; BURBS UP TO 30\"...</a><br><a href=\"http://washington.cbslocal.com/2016/01/19/winter-is-finally-here-deep-freeze-and-snow-in-the-forecast/\">Mayor Requests Help From National Guard...</a><br><a href=\"http://www.accuweather.com/en/weather-news/snow-storm-travel-disruptions-aim-for-nyc-dc-boston-philadelphia-friday-saturday/54870622\">UPDATE...</a><br><a href=\"http://www.infowars.com/snowmaggedon2016-empty-store-shelves-as-panicked-shoppers-ransack-grocery-stores/\">Anxious Shoppers Ransack Grocery Stores...</a><br><a href=\"http://motherboard.vice.com/read/dark-web-users-are-worried-snowstorm-jonas-will-disrupt-their-deliveries\">Dark Web Users Fear Delivery Disruptions...</a><br><a href=\"https://www.washingtonpost.com/news/to-your-health/wp/2016/01/21/heres-why-some-people-drop-dead-while-shoveling-snow/\">Cold weather, shoveling form heart attack 'perfect storm'...</a><br></div></font><br><div class=\"feedflare\"> <a href=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?a=Mtf4NlmV8XU:vDGXzaysxPw:yIl2AUoC8zA\"><img src=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?d=yIl2AUoC8zA\" border=\"0\"></img></a> <a href=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?a=Mtf4NlmV8XU:vDGXzaysxPw:V_sGLiPBpWU\"><img src=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?i=Mtf4NlmV8XU:vDGXzaysxPw:V_sGLiPBpWU\" border=\"0\"></img></a> <a href=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?a=Mtf4NlmV8XU:vDGXzaysxPw:qj6IDK7rITs\"><img src=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?d=qj6IDK7rITs\" border=\"0\"></img></a> <a href=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?a=Mtf4NlmV8XU:vDGXzaysxPw:gIN9vFwOqvQ\"><img src=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?i=Mtf4NlmV8XU:vDGXzaysxPw:gIN9vFwOqvQ\" border=\"0\"></img></a> </div><img src=\"http://feeds.feedburner.com/~r/DrudgeReportFeed/~4/Mtf4NlmV8XU\" height=\"1\" width=\"1\" alt=\"\"/>";
NSString *stringWithoutWhiteSpace = [descriptionString stringByReplacingOccurrencesOfString:@" " withString:@""];
NSInteger srcLocation = [stringWithoutWhiteSpace rangeOfString:@"src="].location;
if ( srcLocation!= NSNotFound) {
NSString *firstSrcImg = [stringWithoutWhiteSpace substringFromIndex:srcLocation];
NSArray *componment = [firstSrcImg componentsSeparatedByString:@"\""];
NSString *url = componment[1];
NSLog(@"%@", url);
}
i invite you to try it and tell me if it respond to your question ... i can give another code that return all img urls :)
SECOND UPDATE For the example i have done here a method that you can use:
- (NSString*) getNextURLFromString:(NSString*) str withURLTag:(NSString*) urlTag{
NSString *stringWithoutWhiteSpace = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
NSInteger srcLocation = [stringWithoutWhiteSpace rangeOfString:urlTag].location;
if ( srcLocation!= NSNotFound) {
NSString *firstSrcImg = [stringWithoutWhiteSpace substringFromIndex:srcLocation];
NSArray *componment = [firstSrcImg componentsSeparatedByString:@"\""];
NSString *url = componment[1];
return url;
}
return nil;
}
for the urlTag
param put @"src="
and for the str
param put the description tag value
UPDATE N° 3
here a method that return all images url
- (NSArray*) getAllURLFromString:(NSString*) str withURLTag:(NSString*) urlTag{
NSMutableArray *result = [NSMutableArray array];
NSString *stringWithoutWhiteSpace = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
NSInteger srcLocation = [stringWithoutWhiteSpace rangeOfString:urlTag].location;
if ( srcLocation!= NSNotFound) {
NSString *firstSrcImg = [stringWithoutWhiteSpace substringFromIndex:srcLocation];
NSArray *componment = [firstSrcImg componentsSeparatedByString:@"\""];
if ([componment count]>1) {
NSString *url = componment[1];
[result addObject:url];
NSArray *nextComponent = [stringWithoutWhiteSpace componentsSeparatedByString:url];
if ([nextComponent count]>1) {
[result addObjectsFromArray:[self getAllURLFromString:nextComponent[1] withURLTag:urlTag]];
}
}
return result;
}
return result;
}
for the urlTag
param put @"src="
and for the str
param put the description tag value
Upvotes: 0
Reputation: 1922
After some research, I've managed to solve my problem. I just needed a little practice with using NSRange
. The idea is, in my case, that when I have a description that has the NSString
"img style" in it, I know for a fact that I need the first "src="whateverImageURL" string that I can get. I do this in the following code:
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:@"item"]) {
NSString *filteredTitle = [title stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *filteredLink = [link stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (![filteredLink containsString:@"https://itunes.apple.com/"]) {
[item setObject:filteredTitle forKey:@"title"];
[item setObject:filteredLink forKey:@"link"];
[item setObject:description forKey:@"description"];
if ([description rangeOfString:@"img style"].location != NSNotFound) {
NSString *finalImageURL;
NSRange startRange = [description rangeOfString:@"src=\""];
finalImageURL = [description substringFromIndex:startRange.location];
finalImageURL = [finalImageURL substringFromIndex:startRange.length];
NSRange endRange = [finalImageURL rangeOfString:@"\""];
finalImageURL = [finalImageURL substringToIndex:endRange.location];
}
[feeds addObject:[item copy]];
}
}
}
Upvotes: 0
Reputation: 438
You'l have to do the following in ur
foundCharacters: method.
else if ([element isEqualToString:@"description"])
{
[description appendString:string];
if ([description rangeOfString:@"img"].location != NSNotFound)
{
NSRange firstRange = [previewImage rangeOfString:@"src="];
NSRange endRange = [[previewImage substringFromIndex:firstRange.location] rangeOfString:@" width=\""];
NSString *finalLink = [[NSString alloc] init];
finalLink = [previewImage substringWithRange:NSMakeRange(firstRange.location, endRange.location)];
NSString *match = @"src=\"";
NSString *postMatch;
NSScanner *scanner = [NSScanner scannerWithString:finalLink];
[scanner scanString:match intoString:nil];
postMatch = [finalLink substringFromIndex:scanner.scanLocation];
NSString *finalURL = [postMatch stringByAppendingString:@""];
description = finalURL;
}
}
}
Here i m storing the URL in previewImage.
Hope it works for u good luck.....
Upvotes: 1