IOS XML解析。如何为同一对象加载不同的键
我正在做RSSFeed项目。我想从五个不同url的XML中获取数据 1) -雅虎网站 2) -谷歌 3) -今日美国 我能够获取诸如标题和描述等数据 键“Ttile”的IOS XML解析。如何为同一对象加载不同的键,ios,xml-parsing,Ios,Xml Parsing,我正在做RSSFeed项目。我想从五个不同url的XML中获取数据 1) -雅虎网站 2) -谷歌 3) -今日美国 我能够获取诸如标题和描述等数据 键“Ttile”的对象和键“@PUBDATE”的对象 但就图像而言,所有RSS提要都使用不同的键进行图像处理 键“图像”的对象、键“src”的对象、键“媒体:内容”的对象 使用Objectforkey:@“媒体:内容” 但其他链接使用不同的Objectforkey,如@“图像”或@“媒体:拇指线” 如何从这个不同的键中获取它,或者如何在单个tabl
对象
和键“@PUBDATE”的对象
但就图像而言,所有RSS提要都使用不同的键进行图像处理
键“图像”的对象、键“src”的对象、键“媒体:内容”的对象
使用Objectforkey:@“媒体:内容”
但其他链接使用不同的Objectforkey,如@“图像”或@“媒体:拇指线”
如何从这个不同的键中获取它,或者如何在单个tableview中设置它
我正在使用XML解析
这是我的代码,我可以使用objectforkey:@“Media:content”
从中获取图像,但我不知道如何为图像设置其他键
//MWFeeditem.h
#import <Foundation/Foundation.h>
@interface MWFeedItem : NSObject <NSCoding> {
NSString *identifier; // Item identifier
NSString *title; // Item title
NSString *link; // Item URL
NSDate *date; // Date the item was published
NSDate *updated; // Date the item was updated if available
NSString *summary; // Description of item
NSString *content; // More detailed content (if available)
NSString *author; // Item author
NSString *image; // image for the feed
// Enclosures: Holds 1 or more item enclosures (i.e. podcasts, mp3. pdf, etc)
// - NSArray of NSDictionaries with the following keys:
// url: where the enclosure is located (NSString)
// length: how big it is in bytes (NSNumber)
// type: what its type is, a standard MIME type (NSString)
NSArray *enclosures;
}
@property (nonatomic, copy) NSString *identifier;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *link;
@property (nonatomic, copy) NSDate *date;
@property (nonatomic, copy) NSDate *updated;
@property (nonatomic, copy) NSString *summary;
@property (nonatomic, copy) NSString *content;
@property (nonatomic, copy) NSString *author;
@property (nonatomic, copy) NSArray *enclosures;
@property (nonatomic, copy) NSString *image;
@end
//mwwwsparser.m
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
MWXMLLog(@"NSXMLParser: didEndElement: %@", qName);
@autoreleasepool {
// Parse content as structure (Atom feeds with element type="xhtml")
// - Use elementName not qualifiedName to ignore XML namespaces for XHTML entities
if (parseStructureAsContent) {
// Check for finishing parsing structure as content
if (currentPath.length > pathOfElementWithXHTMLType.length) {
// Close XHTML tag unless it is an empty element
if (!ELEMENT_IS_EMPTY(elementName)) [currentText appendFormat:@"</%@>", elementName];
// Adjust path & don't continue
self.currentPath = [currentPath stringByDeletingLastPathComponent];
// Return
return;
}
// Finish
parseStructureAsContent = NO;
self.pathOfElementWithXHTMLType = nil;
// Continue...
}
// Store data
BOOL processed = NO;
if (currentText) {
// Remove newlines and whitespace from currentText
NSString *processedText = [currentText stringByRemovingNewLinesAndWhitespace];
// Process
switch (feedType) {
case FeedTypeRSS: {
// Specifications
// http://cyber.law.harvard.edu/rss/index.html
// http://web.resource.org/rss/1.0/modules/dc/ Dublin core also seems to be used for RSS 2 as well
// Item
if (!processed) {
if ([currentPath isEqualToString:@"/rss/channel/item/title"]) { if (processedText.length > 0) item.title = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/link"]) { if (processedText.length > 0) item.link = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/author"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/dc:creator"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/guid"]) { if (processedText.length > 0) item.identifier = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/description"]) { if (processedText.length > 0) item.summary = processedText; processed = YES; }
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; }
***// Changes Done here for image //***
else if ([currentPath isEqualToString:@"/rss/channel/item/media:content"])
{
if ([self.currentElementAttributes objectForKey:@"url"])
item.image = self.currentElementAttributes[@"url"];
processed = YES; }
}
为了获得更多的参考,我附上了完整代码的Pastie.org链接
MWFeed解析器的类文件及其更改
应用程序的类文件
您可以为不同的提要使用不同的键,也可以使用不同的包装器 使用不同的包装器的好处是保持一个提要对另一个提要的依赖性较小,这样,如果将来有任何其他密钥可能发生更改,您可以轻松处理,并且还可以保持代码的可读性 您还可以使用如下所示的枚举数据类型
@property(nonatomic,assign)ParserSource feedType;
if (!processed) {
if(self.feedType==YAHOO_FEED)
{
if (!processed) {
if ([currentPath isEqualToString:@"/rss/channel/item/title"]) { if (processedText.length > 0) item.title = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/link"]) { if (processedText.length > 0) item.link = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/author"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/dc:creator"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/guid"]) { if (processedText.length > 0) item.identifier = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/description"]) { if (processedText.length > 0) item.summary = processedText; processed = YES; }
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(self.feedType==GOOGLE_FEED)
{
///////// different key name for image
}
else if(self.feedType==US_DAILY_FEED)
{
///////// different key name for image
}
在“@interface”行上方的MWFeedParser.h中声明ParserSource类型的枚举器
typedef enum {
YAHOO_FEED=0,
GOOGLE_FEED,
US_DAILY_FEED
}ParserSource;
并向ParserSource类型的MWFeedParser类声明一个属性,如下所示
@property(nonatomic,assign)ParserSource feedType;
if (!processed) {
if(self.feedType==YAHOO_FEED)
{
if (!processed) {
if ([currentPath isEqualToString:@"/rss/channel/item/title"]) { if (processedText.length > 0) item.title = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/link"]) { if (processedText.length > 0) item.link = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/author"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/dc:creator"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/guid"]) { if (processedText.length > 0) item.identifier = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/description"]) { if (processedText.length > 0) item.summary = processedText; processed = YES; }
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(self.feedType==GOOGLE_FEED)
{
///////// different key name for image
}
else if(self.feedType==US_DAILY_FEED)
{
///////// different key name for image
}
然后在viewcontroller中,您知道从哪个源接收馈线,您可以在那里设置MWFeedParser的feedType,并修改用于在MWFeedParser.m中的-parser:diEndElement中收集数据的代码,如下所示
@property(nonatomic,assign)ParserSource feedType;
if (!processed) {
if(self.feedType==YAHOO_FEED)
{
if (!processed) {
if ([currentPath isEqualToString:@"/rss/channel/item/title"]) { if (processedText.length > 0) item.title = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/link"]) { if (processedText.length > 0) item.link = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/author"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/dc:creator"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/guid"]) { if (processedText.length > 0) item.identifier = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/description"]) { if (processedText.length > 0) item.summary = processedText; processed = YES; }
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(self.feedType==GOOGLE_FEED)
{
///////// different key name for image
}
else if(self.feedType==US_DAILY_FEED)
{
///////// different key name for image
}
更改-(void)CallForWebService:(NSURL*)url如下
-(void)CallForWebService:(NSURL*)url fromSource:(ParserSource)sourceType
{
}
我看了一下你的MainViewController。m你的订阅源依赖于11个在线源,因此你必须用11种类型创建enum,因为答案很简短,我只提到了三种类型你可以对不同的订阅源使用不同的键,也可以使用不同的包装器 使用不同的包装器的好处是保持一个提要对另一个提要的依赖性较小,这样,如果将来有任何其他密钥可能发生更改,您可以轻松处理,并且还可以保持代码的可读性 您还可以使用如下所示的枚举数据类型
@property(nonatomic,assign)ParserSource feedType;
if (!processed) {
if(self.feedType==YAHOO_FEED)
{
if (!processed) {
if ([currentPath isEqualToString:@"/rss/channel/item/title"]) { if (processedText.length > 0) item.title = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/link"]) { if (processedText.length > 0) item.link = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/author"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/dc:creator"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/guid"]) { if (processedText.length > 0) item.identifier = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/description"]) { if (processedText.length > 0) item.summary = processedText; processed = YES; }
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(self.feedType==GOOGLE_FEED)
{
///////// different key name for image
}
else if(self.feedType==US_DAILY_FEED)
{
///////// different key name for image
}
在“@interface”行上方的MWFeedParser.h中声明ParserSource类型的枚举器
typedef enum {
YAHOO_FEED=0,
GOOGLE_FEED,
US_DAILY_FEED
}ParserSource;
并向ParserSource类型的MWFeedParser类声明一个属性,如下所示
@property(nonatomic,assign)ParserSource feedType;
if (!processed) {
if(self.feedType==YAHOO_FEED)
{
if (!processed) {
if ([currentPath isEqualToString:@"/rss/channel/item/title"]) { if (processedText.length > 0) item.title = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/link"]) { if (processedText.length > 0) item.link = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/author"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/dc:creator"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/guid"]) { if (processedText.length > 0) item.identifier = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/description"]) { if (processedText.length > 0) item.summary = processedText; processed = YES; }
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(self.feedType==GOOGLE_FEED)
{
///////// different key name for image
}
else if(self.feedType==US_DAILY_FEED)
{
///////// different key name for image
}
然后在viewcontroller中,您知道从哪个源接收馈线,您可以在那里设置MWFeedParser的feedType,并修改用于在MWFeedParser.m中的-parser:diEndElement中收集数据的代码,如下所示
@property(nonatomic,assign)ParserSource feedType;
if (!processed) {
if(self.feedType==YAHOO_FEED)
{
if (!processed) {
if ([currentPath isEqualToString:@"/rss/channel/item/title"]) { if (processedText.length > 0) item.title = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/link"]) { if (processedText.length > 0) item.link = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/author"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/dc:creator"]) { if (processedText.length > 0) item.author = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/guid"]) { if (processedText.length > 0) item.identifier = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/description"]) { if (processedText.length > 0) item.summary = processedText; processed = YES; }
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(self.feedType==GOOGLE_FEED)
{
///////// different key name for image
}
else if(self.feedType==US_DAILY_FEED)
{
///////// different key name for image
}
更改-(void)CallForWebService:(NSURL*)url如下
-(void)CallForWebService:(NSURL*)url fromSource:(ParserSource)sourceType
{
}
我看了一下你的MainViewController。m你的提要依赖于11个在线源,因此你必须创建11种类型的enum,因为答案很短,我只提到了三种类型,那么提要解析器是否真的能帮助你,或者您应该使用更通用的工具,如RestKit?不,我只使用feedparser进行xml解析。因此,我建议您考虑一种更通用的解决方案,该解决方案为获取“通用”提要并将其处理为公共模型对象提供特定支持。在这个feedparser中不可能做到吗?我想您可能有一个特定的解决方案为每个不同的源配置,或为每个源配置具有不同提取密钥的包装器。但是我没有直接的MWFeedParser知识…feed parser真的能帮助你吗,或者您应该使用更通用的工具,如RestKit?不,我只使用feedparser进行xml解析。因此,我建议您考虑一种更通用的解决方案,该解决方案为获取“通用”提要并将其处理为公共模型对象提供特定支持。在这个feedparser中不可能做到吗?我想您可能有一个特定的解决方案为每个不同的源配置,或为每个源配置具有不同提取密钥的包装器。不过我没有直接的语法分析器知识…谢谢你的重播。你能再解释一下吗?我不明白。什么是解析器源代码?感谢您的重播,我如何设置feeditem.m中的键?请检查一下。@BadalShah ParserSource是一种枚举数据类型,您不必在feeditem中更改或声明任何键。m,我已经编辑了我的答案谢谢更新的答案,我需要设置
ParserSource
来代替schedulemodetype
对吗?图像的检查键是什么?哦,这是我的错,我把它改成了ParserSource。您可以像下面这样检查“self.feedType==GOOGLE_FEED”,并从不同的源代码中获取图像,以便重播。你能再解释一下吗?我不明白。什么是解析器源代码?感谢您的重播,我如何设置feeditem.m中的键?请检查一下。@BadalShah ParserSource是一种枚举数据类型,您不必在feeditem中更改或声明任何键。m,我已经编辑了我的答案谢谢更新的答案,我需要设置ParserSource
来代替schedulemodetype
对吗?图像的检查键是什么?哦,这是我的错,我把它改成了ParserSource。您可以像下面这样检查“self.feedType==GOOGLE_FEED”,并从不同的来源获取图像