Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ability for the developer to specify other XML elements to parse. #43

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Classes/MWFeedItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,18 @@
// length: how big it is in bytes (NSNumber)
// type: what its type is, a standard MIME type (NSString)
NSArray *enclosures;


// Rick Russell (@ossmac) 12/28/2011
//
// CustomProperties: is a NSDictionary that contains any items that were
// requested in the feed request by passing in a NSArray of NSStrings with the
// keys to parse
// - NSDictionary will contain keys matching the values passed in the NSArray
// and the values will be NSStrings of the values for that key if they are
// found in the item being parsed. If the key is not found for the item in
// the XML being parsed it will be nil.
NSDictionary *customProperities;

}

@property (nonatomic, copy) NSString *identifier;
Expand All @@ -56,5 +67,7 @@
@property (nonatomic, copy) NSString *summary;
@property (nonatomic, copy) NSString *content;
@property (nonatomic, copy) NSArray *enclosures;
@property (nonatomic, copy) NSDictionary *customProperties;

@end

5 changes: 4 additions & 1 deletion Classes/MWFeedItem.m
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

@implementation MWFeedItem

@synthesize identifier, title, link, date, updated, summary, content, enclosures;
@synthesize identifier, title, link, date, updated, summary, content, enclosures, customProperties;

#pragma mark NSObject

Expand All @@ -55,6 +55,7 @@ - (void)dealloc {
[summary release];
[content release];
[enclosures release];
[customProperities release];
[super dealloc];
}

Expand All @@ -70,6 +71,7 @@ - (id)initWithCoder:(NSCoder *)decoder {
summary = [[decoder decodeObjectForKey:@"summary"] retain];
content = [[decoder decodeObjectForKey:@"content"] retain];
enclosures = [[decoder decodeObjectForKey:@"enclosures"] retain];
customProperities = [[decoder decodeObjectForKey:@"customProperties"] retain];
}
return self;
}
Expand All @@ -83,6 +85,7 @@ - (void)encodeWithCoder:(NSCoder *)encoder {
if (summary) [encoder encodeObject:summary forKey:@"summary"];
if (content) [encoder encodeObject:content forKey:@"content"];
if (enclosures) [encoder encodeObject:enclosures forKey:@"enclosures"];
if (customProperities) [encoder encodeObject:customProperities forKey:@"customProperities"];
}

@end
8 changes: 8 additions & 0 deletions Classes/MWFeedParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ typedef enum { FeedTypeUnknown, FeedTypeRSS, FeedTypeRSS1, FeedTypeAtom } FeedTy
NSXMLParser *feedParser;
FeedType feedType;
NSDateFormatter *dateFormatterRFC822, *dateFormatterRFC3339;

// Rick Russell (@ossmac) - 12/28/2011
// This is an array of custom keys as NSStrings that are to be parsed
// from each item.
NSArray *customKeys;

// Parsing State
NSURL *url;
Expand Down Expand Up @@ -117,6 +122,9 @@ typedef enum { FeedTypeUnknown, FeedTypeRSS, FeedTypeRSS1, FeedTypeAtom } FeedTy
// Set whether to download asynchronously or synchronously
@property (nonatomic) ConnectionType connectionType;

// Set with a array of NSStrings as custom keys to parse from the feed
@property (nonatomic, copy) NSArray *customKeys;

// Whether parsing was stopped
@property (nonatomic, readonly, getter=isStopped) BOOL stopped;

Expand Down
34 changes: 30 additions & 4 deletions Classes/MWFeedParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ @implementation MWFeedParser

// Properties
@synthesize url, delegate;
@synthesize urlConnection, asyncData, asyncTextEncodingName, connectionType;
@synthesize feedParseType, feedParser, currentPath, currentText, currentElementAttributes, item, info;
@synthesize urlConnection, asyncData, asyncTextEncodingName, connectionType, customKeys;
@synthesize feedParseType, feedParser, currentPath, currentText, currentElementAttributes, item, info, tmpDictionary;
@synthesize pathOfElementWithXHTMLType;
@synthesize stopped, failed, parsing;

Expand Down Expand Up @@ -109,6 +109,7 @@ - (void)dealloc {
[item release];
[info release];
[pathOfElementWithXHTMLType release];
[customKeys release];
[super dealloc];
}

Expand Down Expand Up @@ -535,6 +536,7 @@ - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName nam
MWFeedItem *newItem = [[MWFeedItem alloc] init];
self.item = newItem;
[newItem release];
tmpDictionary = [[NSMutableDictionary alloc] init];

// Return
[pool drain];
Expand Down Expand Up @@ -569,6 +571,7 @@ - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName nam

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {

MWXMLLog(@"NSXMLParser: didEndElement: %@", qName);

// Pool
Expand Down Expand Up @@ -621,7 +624,13 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
else if ([currentPath isEqualToString:@"/rss/channel/item/content:encoded"]) { if (processedText.length > 0) item.content = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/pubDate"]) { if (processedText.length > 0) item.date = [NSDate dateFromInternetDateTimeString:processedText formatHint:DateFormatHintRFC822]; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/enclosure"]) { [self createEnclosureFromAttributes:currentElementAttributes andAddToItem:item]; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/dc:date"]) { if (processedText.length > 0) item.date = [NSDate dateFromInternetDateTimeString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/dc:date"]) { if (processedText.length > 0) item.date = [NSDate dateFromInternetDateTimeString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
else if ([customKeys count]) {
[customKeys enumerateObjectsUsingBlock:^(id key, NSUInteger idx, BOOL *stop) {
NSString *path = [NSString stringWithFormat:@"/rss/channel/item/%@", key];
if ([currentPath isEqualToString: path]) { if (processedText.length > 0) [tmpDictionary setValue:processedText forKey:key]; }
}];
}
}

// Info
Expand All @@ -644,6 +653,12 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
else if ([currentPath isEqualToString:@"/rdf:RDF/item/content:encoded"]) { if (processedText.length > 0) item.content = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rdf:RDF/item/dc:date"]) { if (processedText.length > 0) item.date = [NSDate dateFromInternetDateTimeString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
else if ([currentPath isEqualToString:@"/rdf:RDF/item/enc:enclosure"]) { [self createEnclosureFromAttributes:currentElementAttributes andAddToItem:item]; processed = YES; }
else if ([customKeys count]) {
[customKeys enumerateObjectsUsingBlock:^(id key, NSUInteger idx, BOOL *stop) {
NSString *path = [NSString stringWithFormat:@"/rdf:RDF/item/%@", key];
if ([currentPath isEqualToString: path]) { if (processedText.length > 0) [tmpDictionary setValue:processedText forKey:key]; }
}];
}
}

// Info
Expand All @@ -666,6 +681,12 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
else if ([currentPath isEqualToString:@"/feed/entry/content"]) { if (processedText.length > 0) item.content = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/feed/entry/published"]) { if (processedText.length > 0) item.date = [NSDate dateFromInternetDateTimeString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
else if ([currentPath isEqualToString:@"/feed/entry/updated"]) { if (processedText.length > 0) item.updated = [NSDate dateFromInternetDateTimeString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
else if ([customKeys count]) {
[customKeys enumerateObjectsUsingBlock:^(id key, NSUInteger idx, BOOL *stop) {
NSString *path = [NSString stringWithFormat:@"/feed/entry/%@", key];
if ([currentPath isEqualToString: path]) { if (processedText.length > 0) [tmpDictionary setValue:processedText forKey:key]; }
}];
}
}

// Info
Expand All @@ -688,7 +709,12 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
if (!processed) {
if (((feedType == FeedTypeRSS || feedType == FeedTypeRSS1) && [qName isEqualToString:@"item"]) ||
(feedType == FeedTypeAtom && [qName isEqualToString:@"entry"])) {

if([tmpDictionary count]) {
item.customProperties = tmpDictionary;
MWXMLLog(@"NSXMLParser: customProperity: %@ - %@", );
}
[tmpDictionary release];

// Dispatch item to delegate
[self dispatchFeedItemToDelegate];

Expand Down
1 change: 1 addition & 0 deletions Classes/MWFeedParser_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
@property (nonatomic, retain) MWFeedItem *item;
@property (nonatomic, retain) MWFeedInfo *info;
@property (nonatomic, copy) NSString *pathOfElementWithXHTMLType;
@property (nonatomic, retain) NSMutableDictionary *tmpDictionary;

#pragma mark Private Methods

Expand Down
12 changes: 9 additions & 3 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ MWFeedParser is an Objective-C framework for downloading and parsing RSS (1.* an
- Content (detailed item content, if available)
- Enclosures (i.e. podcasts, mp3, pdf, etc)
- Identifier (an item's guid/id)
- customProperties (Dictionary containing any custom elements if the keys are requested in the customKeys configuration property. The dictionary will use the element name as the key and the values will be stored as strings in the dictionary)

If you use MWFeedParser on your iPhone/iPad app then please do let me know, I'd love to check it out :)

Expand All @@ -25,7 +26,7 @@ If you use MWFeedParser on your iPhone/iPad app then please do let me know, I'd
limited to) that of events, news, experiences and activities, for the
purpose of any concept relating to diary/journal keeping.

The full licence can be found at the end of this document.
The full license can be found at the end of this document.


## Demo / Example App
Expand Down Expand Up @@ -56,6 +57,11 @@ Set whether the parser should connect and download the feed data synchronously o
// Connection type
feedParser.connectionType = ConnectionTypeSynchronously;

An array of the elements of to search for in the items in addition to the standard fields:

// Custom Keys
feedParser.customKeys = [NSArray arrayWithObjects: @"itunes:duration", @"itunes:author",nil];

Initiate parsing:

// Begin parsing
Expand Down Expand Up @@ -111,7 +117,7 @@ Here is a list of the available properties for feed info and item objects:
- `item.content` (`NSString`)
- `item.enclosures` (`NSArray` of `NSDictionary` with keys `url`, `type` and `length`)
- `item.identifier` (`NSString`)

- `item.customProperties` (`NSDictionary`)

## Using the data

Expand Down Expand Up @@ -212,4 +218,4 @@ Contact
===============

Website: <http://michaelwaterfall.com>
Twitter: <http://twitter.com/mwaterfall>
Twitter: <http://twitter.com/mwaterfall>