From c165d991d9b2d916fd9ac62de51fcdde99b1d5f8 Mon Sep 17 00:00:00 2001 From: Leo Date: Thu, 22 Jan 2015 11:07:17 +1100 Subject: [PATCH 1/5] added subtitle in FeedInfo - atom only --- Classes/MWFeedInfo.h | 3 +++ Classes/MWFeedInfo.m | 5 +++++ Classes/MWFeedParser.m | 4 +++- README.md | 7 ++++++- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Classes/MWFeedInfo.h b/Classes/MWFeedInfo.h index 3473071..65914de 100644 --- a/Classes/MWFeedInfo.h +++ b/Classes/MWFeedInfo.h @@ -36,6 +36,7 @@ NSString *summary; // Feed summary / description NSURL *url; // Feed url + NSString *subtitle; } @property (nonatomic, copy) NSString *title; @@ -43,4 +44,6 @@ @property (nonatomic, copy) NSString *summary; @property (nonatomic, copy) NSURL *url; +@property (nonatomic, copy) NSString *subtitle; + @end diff --git a/Classes/MWFeedInfo.m b/Classes/MWFeedInfo.m index d762318..a774eb1 100644 --- a/Classes/MWFeedInfo.m +++ b/Classes/MWFeedInfo.m @@ -34,6 +34,7 @@ @implementation MWFeedInfo @synthesize title, link, summary, url; +@synthesize subtitle; #pragma mark NSObject @@ -54,6 +55,8 @@ - (id)initWithCoder:(NSCoder *)decoder { link = [decoder decodeObjectForKey:@"link"]; summary = [decoder decodeObjectForKey:@"summary"]; url = [decoder decodeObjectForKey:@"url"]; + + subtitle = [decoder decodeObjectForKey:@"subtitle"]; } return self; } @@ -63,6 +66,8 @@ - (void)encodeWithCoder:(NSCoder *)encoder { if (link) [encoder encodeObject:link forKey:@"link"]; if (summary) [encoder encodeObject:summary forKey:@"summary"]; if (url) [encoder encodeObject:url forKey:@"url"]; + + if (subtitle) [encoder encodeObject:title forKey:@"subtitle"]; } @end diff --git a/Classes/MWFeedParser.m b/Classes/MWFeedParser.m index 7d900ad..fa3f2f6 100644 --- a/Classes/MWFeedParser.m +++ b/Classes/MWFeedParser.m @@ -665,6 +665,8 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName if ([currentPath isEqualToString:@"/feed/title"]) { if (processedText.length > 0) info.title = processedText; processed = YES; } else if ([currentPath isEqualToString:@"/feed/description"]) { if (processedText.length > 0) info.summary = processedText; processed = YES; } else if ([currentPath isEqualToString:@"/feed/link"]) { [self processAtomLink:currentElementAttributes andAddToMWObject:info]; processed = YES;} + + else if ([currentPath isEqualToString:@"/feed/subtitle"]) { if (processedText.length > 0) info.subtitle = processedText; processed = YES; } } break; @@ -946,4 +948,4 @@ - (BOOL)processAtomLink:(NSDictionary *)attributes andAddToMWObject:(id)MWObject return NO; } -@end \ No newline at end of file +@end diff --git a/README.md b/README.md index f6e67d4..a496d33 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +I'm working on YouTube feed parsing and I'd like to add support for some extra fields like info.subtitle. + +Documents: https://developers.google.com/youtube/2.0/developers_guide_protocol_playlists +Example: https://gdata.youtube.com/feeds/api/playlists/PLvEIxIeBRKSjprrvlbAcbVjzHsnH9PjDX?v=2 + # MWFeedParser — An RSS and Atom web feed parser for iOS MWFeedParser is an Objective-C framework for downloading and parsing RSS (1.* and 2.*) and Atom web feeds. It is a very simple and clean implementation that reads the following information from a web feed: @@ -221,4 +226,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file +THE SOFTWARE. From 89c045ffb347ed49909a0e4ceffcd39029dbf461 Mon Sep 17 00:00:00 2001 From: Leo Date: Thu, 22 Jan 2015 16:53:03 +1100 Subject: [PATCH 2/5] removed hardcoded subtitle; added rawTexts and rawAttrs --- Classes/MWFeedInfo.h | 8 ++++---- Classes/MWFeedInfo.m | 17 +++++++++++----- Classes/MWFeedItem.h | 5 ++++- Classes/MWFeedItem.m | 12 +++++++++++ Classes/MWFeedParser.h | 5 ++++- Classes/MWFeedParser.m | 28 +++++++++++++++++++++++--- Classes/RootViewController.m | 9 +++++++-- MWFeedParser.xcodeproj/project.pbxproj | 4 +--- README.md | 6 +++++- 9 files changed, 74 insertions(+), 20 deletions(-) diff --git a/Classes/MWFeedInfo.h b/Classes/MWFeedInfo.h index 65914de..4b9ceed 100644 --- a/Classes/MWFeedInfo.h +++ b/Classes/MWFeedInfo.h @@ -35,15 +35,15 @@ NSString *link; // Feed link NSString *summary; // Feed summary / description NSURL *url; // Feed url - - NSString *subtitle; + NSMutableDictionary *rawTexts; // raw data + NSMutableDictionary *rawAttrs; // raw data } @property (nonatomic, copy) NSString *title; @property (nonatomic, copy) NSString *link; @property (nonatomic, copy) NSString *summary; @property (nonatomic, copy) NSURL *url; - -@property (nonatomic, copy) NSString *subtitle; +@property (nonatomic, copy) NSMutableDictionary *rawTexts; +@property (nonatomic, copy) NSMutableDictionary *rawAttrs; @end diff --git a/Classes/MWFeedInfo.m b/Classes/MWFeedInfo.m index a774eb1..4969fc5 100644 --- a/Classes/MWFeedInfo.m +++ b/Classes/MWFeedInfo.m @@ -34,7 +34,18 @@ @implementation MWFeedInfo @synthesize title, link, summary, url; -@synthesize subtitle; +@synthesize rawTexts, rawAttrs; + +- (id)init +{ + self = [super init]; + if (self) + { + rawTexts = [[NSMutableDictionary alloc] init]; + rawAttrs = [[NSMutableDictionary alloc] init]; + } + return self; +} #pragma mark NSObject @@ -55,8 +66,6 @@ - (id)initWithCoder:(NSCoder *)decoder { link = [decoder decodeObjectForKey:@"link"]; summary = [decoder decodeObjectForKey:@"summary"]; url = [decoder decodeObjectForKey:@"url"]; - - subtitle = [decoder decodeObjectForKey:@"subtitle"]; } return self; } @@ -66,8 +75,6 @@ - (void)encodeWithCoder:(NSCoder *)encoder { if (link) [encoder encodeObject:link forKey:@"link"]; if (summary) [encoder encodeObject:summary forKey:@"summary"]; if (url) [encoder encodeObject:url forKey:@"url"]; - - if (subtitle) [encoder encodeObject:title forKey:@"subtitle"]; } @end diff --git a/Classes/MWFeedItem.h b/Classes/MWFeedItem.h index 47bea85..1fc5038 100644 --- a/Classes/MWFeedItem.h +++ b/Classes/MWFeedItem.h @@ -46,7 +46,8 @@ // length: how big it is in bytes (NSNumber) // type: what its type is, a standard MIME type (NSString) NSArray *enclosures; - + NSMutableDictionary *rawTexts; // raw data + NSMutableDictionary *rawAttrs; // raw data } @property (nonatomic, copy) NSString *identifier; @@ -58,5 +59,7 @@ @property (nonatomic, copy) NSString *content; @property (nonatomic, copy) NSString *author; @property (nonatomic, copy) NSArray *enclosures; +@property (nonatomic, copy) NSMutableDictionary *rawTexts; +@property (nonatomic, copy) NSMutableDictionary *rawAttrs; @end diff --git a/Classes/MWFeedItem.m b/Classes/MWFeedItem.m index 7ccb7e4..a8f8c57 100644 --- a/Classes/MWFeedItem.m +++ b/Classes/MWFeedItem.m @@ -34,6 +34,18 @@ @implementation MWFeedItem @synthesize identifier, title, link, date, updated, summary, content, author, enclosures; +@synthesize rawTexts, rawAttrs; + +- (id)init +{ + self = [super init]; + if (self) + { + rawTexts = [[NSMutableDictionary alloc] init]; + rawAttrs = [[NSMutableDictionary alloc] init]; + } + return self; +} #pragma mark NSObject diff --git a/Classes/MWFeedParser.h b/Classes/MWFeedParser.h index d2a8a39..40be5a1 100644 --- a/Classes/MWFeedParser.h +++ b/Classes/MWFeedParser.h @@ -126,6 +126,9 @@ typedef enum { FeedTypeUnknown, FeedTypeRSS, FeedTypeRSS1, FeedTypeAtom } FeedTy // Whether parsing is in progress @property (nonatomic, readonly, getter=isParsing) BOOL parsing; +// Allow user to access raw data for feed info and items for ATOM feeds +@property (nonatomic, readonly, getter=isParsing) BOOL enableRawAtom; + #pragma mark Public Methods // Init MWFeedParser with a URL string @@ -143,4 +146,4 @@ typedef enum { FeedTypeUnknown, FeedTypeRSS, FeedTypeRSS1, FeedTypeAtom } FeedTy // Returns the URL - (NSURL *)url; -@end \ No newline at end of file +@end diff --git a/Classes/MWFeedParser.m b/Classes/MWFeedParser.m index fa3f2f6..3d78820 100644 --- a/Classes/MWFeedParser.m +++ b/Classes/MWFeedParser.m @@ -54,6 +54,7 @@ @implementation MWFeedParser @synthesize feedParseType, feedParser, currentPath, currentText, currentElementAttributes, item, info; @synthesize pathOfElementWithXHTMLType; @synthesize stopped, failed, parsing; +@synthesize enableRawAtom; #pragma mark - #pragma mark NSObject @@ -63,7 +64,8 @@ - (id)init { // Defaults feedParseType = ParseTypeFull; - connectionType = ConnectionTypeSynchronously; + connectionType = ConnectionTypeAsynchronously; + enableRawAtom = YES; // Date Formatters // Good info on internet dates here: http://developer.apple.com/iphone/library/qa/qa2010/qa1480.html @@ -658,6 +660,16 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName else if ([currentPath isEqualToString:@"/feed/entry/dc:creator"]) { if (processedText.length > 0) item.author = 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; } + + if (self.enableRawAtom) { + if (currentText.length > 0) { + NSString* text = [NSString stringWithString:currentText]; + item.rawTexts[currentPath] = text; + } + if (currentElementAttributes.count > 0) { + item.rawAttrs[currentPath] = currentElementAttributes; + } + } } // Info @@ -666,9 +678,19 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName else if ([currentPath isEqualToString:@"/feed/description"]) { if (processedText.length > 0) info.summary = processedText; processed = YES; } else if ([currentPath isEqualToString:@"/feed/link"]) { [self processAtomLink:currentElementAttributes andAddToMWObject:info]; processed = YES;} - else if ([currentPath isEqualToString:@"/feed/subtitle"]) { if (processedText.length > 0) info.subtitle = processedText; processed = YES; } + if (self.enableRawAtom) { + if (currentText.length > 0) { + NSString* text = [NSString stringWithString:currentText]; + info.rawTexts[currentPath] = text; + } + if (currentElementAttributes.count > 0) { + info.rawAttrs[currentPath] = currentElementAttributes; + } + } } - + + // NSLog(@"ATOM raw: %@\n%@\n%@", currentPath, currentText, currentElementAttributes); + break; } default: break; diff --git a/Classes/RootViewController.m b/Classes/RootViewController.m index f11ac8f..62408ca 100644 --- a/Classes/RootViewController.m +++ b/Classes/RootViewController.m @@ -59,7 +59,8 @@ - (void)viewDidLoad { // Parse // NSURL *feedURL = [NSURL URLWithString:@"http://images.apple.com/main/rss/hotnews/hotnews.rss"]; // NSURL *feedURL = [NSURL URLWithString:@"http://feeds.mashable.com/Mashable"]; - NSURL *feedURL = [NSURL URLWithString:@"http://techcrunch.com/feed/"]; +// NSURL *feedURL = [NSURL URLWithString:@"http://techcrunch.com/feed/"]; + NSURL *feedURL = [NSURL URLWithString:@"https://gdata.youtube.com/feeds/api/playlists/PLvEIxIeBRKSjprrvlbAcbVjzHsnH9PjDX?v=2"]; feedParser = [[MWFeedParser alloc] initWithFeedURL:feedURL]; feedParser.delegate = self; feedParser.feedParseType = ParseTypeFull; // Parse feed info and all items @@ -99,12 +100,16 @@ - (void)feedParserDidStart:(MWFeedParser *)parser { - (void)feedParser:(MWFeedParser *)parser didParseFeedInfo:(MWFeedInfo *)info { NSLog(@"Parsed Feed Info: “%@”", info.title); + //NSLog(@"Parsed Feed Info texts: “%@”", info.rawTexts); + //NSLog(@"Parsed Feed Info attrs: “%@”", info.rawAttrs); self.title = info.title; } - (void)feedParser:(MWFeedParser *)parser didParseFeedItem:(MWFeedItem *)item { NSLog(@"Parsed Feed Item: “%@”", item.title); - if (item) [parsedItems addObject:item]; + //NSLog(@"Parsed Feed Item texts: “%@”", item.rawTexts); + //NSLog(@"Parsed Feed Item attrs: “%@”", item.rawAttrs); + if (item) [parsedItems addObject:item]; } - (void)feedParserDidFinish:(MWFeedParser *)parser { diff --git a/MWFeedParser.xcodeproj/project.pbxproj b/MWFeedParser.xcodeproj/project.pbxproj index f7f461c..9ab0e00 100755 --- a/MWFeedParser.xcodeproj/project.pbxproj +++ b/MWFeedParser.xcodeproj/project.pbxproj @@ -221,7 +221,7 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0420; + LastUpgradeCheck = 0610; ORGANIZATIONNAME = "Michael Waterfall"; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MWFeedParser" */; @@ -317,7 +317,6 @@ C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; CLANG_ENABLE_OBJC_ARC = NO; CODE_SIGN_IDENTITY = ""; GCC_C_LANGUAGE_STANDARD = c99; @@ -333,7 +332,6 @@ C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; CLANG_ENABLE_OBJC_ARC = NO; CODE_SIGN_IDENTITY = ""; GCC_C_LANGUAGE_STANDARD = c99; diff --git a/README.md b/README.md index a496d33..973f965 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,12 @@ -I'm working on YouTube feed parsing and I'd like to add support for some extra fields like info.subtitle. +I'm working on YouTube feed parsing and I'd like to add support for some extra fields as rawTexts and rawAttrs. Documents: https://developers.google.com/youtube/2.0/developers_guide_protocol_playlists Example: https://gdata.youtube.com/feeds/api/playlists/PLvEIxIeBRKSjprrvlbAcbVjzHsnH9PjDX?v=2 +For example: + let sub = info.rawTexts["/feed/subtitle"] as String? + let url = item.rawAttrs["/feed/entry/media:group/media:thumbnail"]?["url"] as String? + # MWFeedParser — An RSS and Atom web feed parser for iOS MWFeedParser is an Objective-C framework for downloading and parsing RSS (1.* and 2.*) and Atom web feeds. It is a very simple and clean implementation that reads the following information from a web feed: From 5b542cfcfef223799c75644b47968b7ed1a4094e Mon Sep 17 00:00:00 2001 From: Leo Date: Thu, 22 Jan 2015 16:54:21 +1100 Subject: [PATCH 3/5] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 973f965..026ee7e 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ Documents: https://developers.google.com/youtube/2.0/developers_guide_protocol_p Example: https://gdata.youtube.com/feeds/api/playlists/PLvEIxIeBRKSjprrvlbAcbVjzHsnH9PjDX?v=2 For example: - let sub = info.rawTexts["/feed/subtitle"] as String? - let url = item.rawAttrs["/feed/entry/media:group/media:thumbnail"]?["url"] as String? +- let sub = info.rawTexts["/feed/subtitle"] as String? +- let url = item.rawAttrs["/feed/entry/media:group/media:thumbnail"]?["url"] as String? # MWFeedParser — An RSS and Atom web feed parser for iOS From 71f033ac1dd8424098cee775eb358334dcccb584 Mon Sep 17 00:00:00 2001 From: Leo Date: Thu, 22 Jan 2015 17:16:04 +1100 Subject: [PATCH 4/5] added support for attributes with same name, see README --- Classes/MWFeedParser.m | 9 ++++++++- Classes/RootViewController.m | 2 +- README.md | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Classes/MWFeedParser.m b/Classes/MWFeedParser.m index 3d78820..bf0172f 100644 --- a/Classes/MWFeedParser.m +++ b/Classes/MWFeedParser.m @@ -667,7 +667,14 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName item.rawTexts[currentPath] = text; } if (currentElementAttributes.count > 0) { - item.rawAttrs[currentPath] = currentElementAttributes; + if (item.rawAttrs[currentPath] == nil) { + item.rawAttrs[currentPath] = currentElementAttributes; + } else if ([item.rawAttrs[currentPath] isKindOfClass:NSArray.class]) { + [item.rawAttrs[currentPath] addObject:currentElementAttributes]; + } else { + NSDictionary* attr = item.rawAttrs[currentPath]; + item.rawAttrs[currentPath] = [NSMutableArray arrayWithObjects:attr, currentElementAttributes, nil]; + } } } } diff --git a/Classes/RootViewController.m b/Classes/RootViewController.m index 62408ca..1b71a75 100644 --- a/Classes/RootViewController.m +++ b/Classes/RootViewController.m @@ -108,7 +108,7 @@ - (void)feedParser:(MWFeedParser *)parser didParseFeedInfo:(MWFeedInfo *)info { - (void)feedParser:(MWFeedParser *)parser didParseFeedItem:(MWFeedItem *)item { NSLog(@"Parsed Feed Item: “%@”", item.title); //NSLog(@"Parsed Feed Item texts: “%@”", item.rawTexts); - //NSLog(@"Parsed Feed Item attrs: “%@”", item.rawAttrs); + NSLog(@"Parsed Feed Item attrs: “%@”", item.rawAttrs); if (item) [parsedItems addObject:item]; } diff --git a/README.md b/README.md index 026ee7e..a49bcd5 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Example: https://gdata.youtube.com/feeds/api/playlists/PLvEIxIeBRKSjprrvlbAcbVjz For example: - let sub = info.rawTexts["/feed/subtitle"] as String? -- let url = item.rawAttrs["/feed/entry/media:group/media:thumbnail"]?["url"] as String? +- let url = item.rawAttrs["/feed/entry/media:group/media:thumbnail"]?[2]?["url"] as String? # MWFeedParser — An RSS and Atom web feed parser for iOS From 392e690052146ee69c9a2f62dfc2c8b66a8c50e0 Mon Sep 17 00:00:00 2001 From: Leo Date: Thu, 22 Jan 2015 17:17:28 +1100 Subject: [PATCH 5/5] added support for attributes with same name for info too --- .gitignore | 3 ++- Classes/MWFeedParser.m | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 0feaf30..e4f38e4 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ xcuserdata Icon .Spotlight-V100 .Trashes +.*.sw* # # Misc @@ -45,4 +46,4 @@ Icon # GitTower # -/Icon.png \ No newline at end of file +/Icon.png diff --git a/Classes/MWFeedParser.m b/Classes/MWFeedParser.m index bf0172f..3c5cfbb 100644 --- a/Classes/MWFeedParser.m +++ b/Classes/MWFeedParser.m @@ -691,7 +691,14 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName info.rawTexts[currentPath] = text; } if (currentElementAttributes.count > 0) { - info.rawAttrs[currentPath] = currentElementAttributes; + if (info.rawAttrs[currentPath] == nil) { + info.rawAttrs[currentPath] = currentElementAttributes; + } else if ([info.rawAttrs[currentPath] isKindOfClass:NSArray.class]) { + [info.rawAttrs[currentPath] addObject:currentElementAttributes]; + } else { + NSDictionary* attr = info.rawAttrs[currentPath]; + info.rawAttrs[currentPath] = [NSMutableArray arrayWithObjects:attr, currentElementAttributes, nil]; + } } } }