网上找到解析XML方法

来源:互联网 发布:centos鼠标失灵 编辑:程序博客网 时间:2024/05/21 13:11
 

iPhone开发技巧之网络篇(1)— 解析XML


  • 16四/10
  • 博主:笑笑
  • 原文链接 : http://www.yifeiyang.net/iphone-web-development-techniques-of-the-chapter-1-parsing-xml/
  • 转载请保留上面文字。

     iPhone的XML库
     XML解析与内存占用
     libxml2 vs NSXMLParser
     NSXMLParser的例子
     libxml2的例子
     项目中添加libxml
     libxml中的SAX解析器
     使用DOM解析
     Google Data APIs
     TouchXML
     KissXML

    iPhone开发技巧之网络篇(1)--- 解析XML

    开发 iPhone 上的网络应用程序的时候时常需要解析XML文档,比如web应用中的SOAP,REST,RSS信息等都是以XML为基础的。掌握XML解析的技术是很重要的。这里我将为大家介绍一下iPhone下解析XML的几种方法,并比较其性能。

    iPhone的XML库

    iPhone中标准的XML解析库有两个,分贝是libxml2和NSXMLParser。

    libxml2由Gnome项目开发、由于是MIT的开放协议,已经移植到许多的平台,在iPhone上也能使用。

    libxml2的特点是比较快。另外作为最基本的XML解析器,提供SAX和DOM解析。并且它对应的XML标准最多,比如名称空间、XPath、XPointer、HTML、XInclude、XSLT、XML Schema、Relax NG等。另外它是用C语言写的,比较高速。

    NSXMLParser是Cocoa中内含的XML解析器。它只提供了SAX解析的功能。因为是Cocoa的一部分、并且API是Objective-C的,所以与Mac系统兼容性强,使用也相对简单。

    XML解析与内存占用

    由于iPhone也是一种嵌入式设备,所以与其他的嵌入式设备一样,同样有内存,CPU等资源占用问题。所以在选择代码库的时候需要考虑性能与内存占用的问题。

    一般XML的解析器有SAX解析和DOM解析两种方式、相比之下SAX比较小巧精干,耗费的内存小。这是因为其设计思想与DOM完全不一样,一边得到数据一边解析,由回调的方式通知得到的数据,没有了DOM树的概念。

    现在的iPhone 3G搭载的RAM是128MB(3GS是256MB)。其中有iPhone OS本身使用的、还有根据用于使用情况不同,比如MP3,邮件,Safari等常驻程序等。基本上自己的程序可使用的内存大小是10MB左右的空间。

    开发XML解析程序的时候,需要注意到XML文件一般都比较大,如果使用DOM的话,消费的内存量肯定很多。所以在iPhone中上面这两种解析器只能使用SAX的解析方式。DOM方式只能在模拟器上使用(比如NSXMLDocument类),放到实际设备上就不管用了。(不过,在下面的章节中我将介绍一种使用DOM的第三方方法,对于小的XML文档还是值得一用的。)

    libxml2 vs NSXMLParser

    一般是使用libxml2的SAX解析器呢,还是使用NSXMLParser能,我们通过下面的SDK中附属的例子XMLPerformance来做个测试。

    相同的XML文档由网络下载,然后解析,比较的结果如下 :

     下载用时解析用时合计NSXMLParser1.419s5.525s7.134slibxml22.520s2.247s2.646s

    可以看到,libxml2比NSXMLParser快得多。这与它们处理的方式有些关系,NSXMLParser中调用SAX API的时候,参数是作为字符串传递的,需要先转换为NSString或者是NSDictionary对象,并且它不像libxml2那样是一边下载一边解析,需要整个文件下载完了才开始解析。所以说建议一般使用libxml2。

    NSXMLParser的例子

    解析的XML代码例子如下:

    12345
    <?xml version="1.0" encoding="UTF-8"?><users>    <user name="hoge" age="20" />    <user name="fuga" age="30" /></users>

    代码如下:

    12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
    static NSString *feedURLString = @"http://www.yifeiyang.net/test/test.xml";- (void)parserDidStartDocument:(NSXMLParser *)parser{    // 解析开始时的处理}- (void)parseXMLFileAtURL:(NSURL *)URL parseError:(NSError **)error{    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];    [parser setDelegate:self];    [parser setShouldProcessNamespaces:NO];    [parser setShouldReportNamespacePrefixes:NO];    [parser setShouldResolveExternalEntities:NO];    [parser parse];    NSError *parseError = [parser parserError];    if (parseError && error) {        *error = parseError;    }    [parser release];}- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{    // 元素开始句柄    if (qName) {        elementName = qName;    }    if ([elementName isEqualToString:@"user"]) {        // 输出属性值        NSLog(@"Name is %@ , Age is %@", [attributeDict objectForKey:@"name"], [attributeDict objectForKey:@"age"]);    }}- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{    // 元素终了句柄    if (qName) {        elementName = qName;    }}- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{    // 取得元素的text}NSError *parseError = nil;[self parseXMLFileAtURL:[NSURL URLWithString:feedURLString] parseError:&parseError];

    实际使用的时候除最后两行以外,所有的当如一个类中,最后两个是启动该类的代码。

    libxml2的例子

    项目中添加libxml

    首先需要将libxml添加到你的工程项目中。

    我们知道,当向项目中添加外部库的时候,如果是程序框架的,比如UIKit.framework,Foundation.framework等放在Sysytem/Library/Frameworks 目录下。SDK放在 /Developer/Platforms/iPhoneOS.platform/Developer/SDKs 目录下。

    但是由于libxml是UNIX的库、位于SDK文件夹的usr/lib下。头文件位于 usr/include 下。


    iphone libxml2

    在 libxml 目录下将 libxml2.2.dylib(或更高版本)添加到项目中。将头文件路径 usr/include/libxml2 也添加到包含路径中。

    以下是libxml2.2.dylib的路径/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS${VER}sdk/usr/lib/libxml2.2.dylib以下是头文件的路径/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS${VER}.sdk/usr/include/libxml2


    iphone libxml2

    libxml中的SAX解析器

    用过SAX解析器的朋友都知道,SAX就是事先登录一些处理函数,当XML解析到属性或要素的时候,回调登录的处理函数。

    以下是一个例子,DownloadOperation实现网络文件的下载,同时交给libxml2的SAX解析器处理:

    123456789101112131415161718192021222324
    // DownloadOperation.h#import <Foundation/Foundation.h>#import <libxml/tree.h>@interface DownloadOperation : NSOperation{    NSURLRequest*           _request;    NSURLConnection*        _connection;    xmlParserCtxtPtr        _parserContext;    BOOL                    _isExecuting, _isFinished;    BOOL                    _isChannel, _isItem;    NSMutableDictionary*    _channel;    NSMutableDictionary*    _currentItem;    NSMutableString*        _currentCharacters;}// Property@property (readonly) NSDictionary* channel;// Initialize- (id)initWithRequest:(NSURLRequest*)request;@end

    首先、#import了libxml/tree.h头文件。然后声明了一个 xmlParserCtxtPtr 变量作为解析器的实例。

    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
    // DownloadOperation.m#import "DownloadOperation.h"@interface DownloadOperation (private)- (void)startElementLocalName:(const xmlChar*)localname        prefix:(const xmlChar*)prefix        URI:(const xmlChar*)URI        nb_namespaces:(int)nb_namespaces        namespaces:(const xmlChar**)namespaces        nb_attributes:(int)nb_attributes        nb_defaulted:(int)nb_defaulted        attributes:(const xmlChar**)attributes;- (void)endElementLocalName:(const xmlChar*)localname        prefix:(const xmlChar*)prefix URI:(const xmlChar*)URI;- (void)charactersFound:(const xmlChar*)ch        len:(int)len;@endstatic void startElementHandler(        void* ctx,        const xmlChar* localname,        const xmlChar* prefix,        const xmlChar* URI,        int nb_namespaces,        const xmlChar** namespaces,        int nb_attributes,        int nb_defaulted,        const xmlChar** attributes){    [(DownloadOperation*)ctx            startElementLocalName:localname            prefix:prefix URI:URI            nb_namespaces:nb_namespaces            namespaces:namespaces            nb_attributes:nb_attributes            nb_defaulted:nb_defaulted            attributes:attributes];}static void endElementHandler(        void* ctx,        const xmlChar* localname,        const xmlChar* prefix,        const xmlChar* URI){    [(DownloadOperation*)ctx            endElementLocalName:localname            prefix:prefix            URI:URI];}static void charactersFoundHandler(        void* ctx,        const xmlChar* ch,        int len){    [(DownloadOperation*)ctx            charactersFound:ch len:len];}static xmlSAXHandler _saxHandlerStruct = {    NULL,            /* internalSubset */    NULL,            /* isStandalone   */    NULL,            /* hasInternalSubset */    NULL,            /* hasExternalSubset */    NULL,            /* resolveEntity */    NULL,            /* getEntity */    NULL,            /* entityDecl */    NULL,            /* notationDecl */    NULL,            /* attributeDecl */    NULL,            /* elementDecl */    NULL,            /* unparsedEntityDecl */    NULL,            /* setDocumentLocator */    NULL,            /* startDocument */    NULL,            /* endDocument */    NULL,            /* startElement*/    NULL,            /* endElement */    NULL,            /* reference */    charactersFoundHandler, /* characters */    NULL,            /* ignorableWhitespace */    NULL,            /* processingInstruction */    NULL,            /* comment */    NULL,            /* warning */    NULL,            /* error */    NULL,            /* fatalError //: unused error() get all the errors */    NULL,            /* getParameterEntity */    NULL,            /* cdataBlock */    NULL,            /* externalSubset */    XML_SAX2_MAGIC,  /* initialized */    NULL,            /* private */    startElementHandler,    /* startElementNs */    endElementHandler,      /* endElementNs */    NULL,            /* serror */};@implementation DownloadOperation// Property@synthesize channel = _channel;//--------------------------------------------------------------//#pragma mark -- Initialize --//--------------------------------------------------------------//+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key{    if ([key isEqualToString:@"isExecuting"] ||        [key isEqualToString:@"isFinished"])    {        return YES;    }    return [super automaticallyNotifiesObserversForKey:key];}- (id)initWithRequest:(NSURLRequest*)request{    if (![super init]) {        return nil;    }    // 实例初始化    _request = [request retain];    _isExecuting = NO;    _isFinished = NO;    _channel = [[NSMutableDictionary dictionary] retain];    [_channel setObject:[NSMutableArray array] forKey:@"items"];    _currentItem = nil;    return self;}- (void)dealloc{    // 内存释放    [_request release], _request = nil;    [_connection cancel];    [_connection release], _connection = nil;    [_channel release], _channel = nil;    [_currentCharacters release], _currentCharacters = nil;    [super dealloc];}//--------------------------------------------------------------//#pragma mark -- Operating --//--------------------------------------------------------------//- (BOOL)isConcurrent{    return YES;}- (BOOL)isExecuting{    return _isExecuting;}- (BOOL)isFinished{    return _isFinished;}- (void)start{    // 开始下载    if (![self isCancelled]) {        // 创建XML解析器        _parserContext = xmlCreatePushParserCtxt(&_saxHandlerStruct, self, NULL, 0, NULL);        // 设定标志        [self setValue:[NSNumber numberWithBool:YES] forKey:@"isExecuting"];        _isChannel = NO;        _isItem = NO;        // 创建连接        [NSURLConnection connectionWithRequest:_request delegate:self];    }}- (void)cancel{    // 释放XML解析器    if (_parserContext) {        xmlFreeParserCtxt(_parserContext), _parserContext = NULL;    }    [_connection cancel], _connection = nil;    [self setValue:[NSNumber numberWithBool:NO] forKey:@"isExecuting"];    [self setValue:[NSNumber numberWithBool:YES] forKey:@"isFinished"];    [super cancel];}//--------------------------------------------------------------//#pragma mark -- NSURLConnection delegate --//--------------------------------------------------------------//- (void)connection:(NSURLConnection*)connection        didReceiveData:(NSData*)data{    // 添加解析数据    xmlParseChunk(_parserContext, (const char*)[data bytes], [data length], 0);}- (void)connectionDidFinishLoading:(NSURLConnection*)connection{    // 添加解析数据(结束)    xmlParseChunk(_parserContext, NULL, 0, 1);    // 释放XML解析器    if (_parserContext) {        xmlFreeParserCtxt(_parserContext), _parserContext = NULL;    }    // 设定标志    _connection = nil;    [self setValue:[NSNumber numberWithBool:NO] forKey:@"isExecuting"];    [self setValue:[NSNumber numberWithBool:YES] forKey:@"isFinished"];}- (void)connection:(NSURLConnection*)connection        didFailWithError:(NSError*)error{    // 释放XML解析器    if (_parserContext) {        xmlFreeParserCtxt(_parserContext), _parserContext = NULL;    }    // 设定标志    _connection = nil;    [self setValue:[NSNumber numberWithBool:NO] forKey:@"isExecuting"];    [self setValue:[NSNumber numberWithBool:YES] forKey:@"isFinished"];}//--------------------------------------------------------------//#pragma mark -- libxml handler --//--------------------------------------------------------------//- (void)startElementLocalName:(const xmlChar*)localname        prefix:(const xmlChar*)prefix        URI:(const xmlChar*)URI        nb_namespaces:(int)nb_namespaces        namespaces:(const xmlChar**)namespaces        nb_attributes:(int)nb_attributes        nb_defaulted:(int)nb_defaulted        attributes:(const xmlChar**)attributes{    // channel    if (strncmp((char*)localname, "channel", sizeof("channel")) == 0) {        _isChannel = YES;        return;    }    // item    if (strncmp((char*)localname, "item", sizeof("item")) == 0) {        _isItem = YES;        _currentItem = [NSMutableDictionary dictionary];        [[_channel objectForKey:@"items"] addObject:_currentItem];        return;    }    // title, link, description    if (strncmp((char*)localname, "title", sizeof("title")) == 0 ||        strncmp((char*)localname, "link", sizeof("link")) == 0 ||        strncmp((char*)localname, "description", sizeof("description")) == 0)    {        // 创建字符串        [_currentCharacters release], _currentCharacters = nil;        _currentCharacters = [[NSMutableString string] retain];    }}- (void)endElementLocalName:(const xmlChar*)localname        prefix:(const xmlChar*)prefix URI:(const xmlChar*)URI{    // channel    if (strncmp((char*)localname, "channel", sizeof("channel")) == 0) {        _isChannel = NO;        return;    }    // item    if (strncmp((char*)localname, "item", sizeof("item")) == 0) {        _isItem = NO;        _currentItem = nil;        return;    }    // title, link, description    if (strncmp((char*)localname, "title", sizeof("title")) == 0 ||        strncmp((char*)localname, "link", sizeof("link")) == 0 ||        strncmp((char*)localname, "description", sizeof("description")) == 0)    {        NSString*   key;        key = [NSString stringWithCString:(char*)localname encoding:NSUTF8StringEncoding];        NSMutableDictionary*    dict = nil;        if (_isItem) {            dict = _currentItem;        }        else if (_isChannel) {            dict = _channel;        }        [dict setObject:_currentCharacters forKey:key];        [_currentCharacters release], _currentCharacters = nil;    }}- (void)charactersFound:(const xmlChar*)ch        len:(int)len{    // 添加解析到的字符串    if (_currentCharacters) {        NSString*   string;        string = [[NSString alloc] initWithBytes:ch length:len encoding:NSUTF8StringEncoding];        [_currentCharacters appendString:string];        [string release];    }}@end

    连接开始的时候(start函数)使用 xmlCreatePushParserCtxt 创建解析器实例,这里注意第二个参数,将DownloadOperation 的实例传到解析器内,这个正是回调函数中的第一个参数 — 作为回调函数的句柄调用类成员函数(当然,不使用实例方法,将回调函数设置成类方法也是可行的。但是当你使用到DownloadOperation中的成员等会有些不便,所以从OO的角度出发,还是传递回调函数的对象实例为佳)。

    开始下载的时候,因为数据是顺序得到的,所以一边下载,一边用 xmlParseChunk 传递给解析器。

    libxml的SAX句柄函数在xmlSAXHandler结构中定义。这个构造体内有30多个句柄定义,一般我们只需要登录其中几个就够了。比如例子中的 startElementNsSAX2Func、endElementNsSAX2Func、charactersSAXFunc 等,他们的定义如下:

    最后,因为用SAX解析,需要知道当前解析的位置,所以标记参数需要合理的使用。

    使用DOM解析

    上面我们已经介绍了,iPhone 中的XML解析器都是SAX的,如果仅仅对于比较小的XML文档,或者说想得到DOM树结构的XML文档来说,使用DOM解析还是有一定价值的(比如针对简单的SOAP,REST文档解析等)。

    Google Data APIs

    这里介绍一种使用第三方类库的方法,具体见这里。其实说是第三方类库,其实还是使用了libxml2,所以前期库文件和头文件的设置与上面libxml2是一致的。并将 -lxml2 加到link的设置中。

    使用的时候,先从这里下载并解冻 Google Data APIs Objective-C Client Library,然后将下面解开的文件拷贝到项目中去。

    1234
    GDataXMLNode.hGDataXMLNode.mGDataDefines.hGDataTargetNamespace.h

    解析的例子如下:

    123456789101112
    <users>    <user id="0">        <name>azalea</name>        <email>azalea@azalea.net</email>        <address country="Japan">Hokkaido</address>    </user>    <user id="1">        <name>Baka.K.El.Doglla</name>        <email>unknown@unknown.net</email>        <address country="Doglla">Doglla</address>    </user></users>

    下面就是使用方法了,DOM的API使用起来还是感觉便利些:

    1234567891011121314151617181920212223242526
    #import "GDataXMLNode.h"- (void)applicationDidFinishLaunching:(UIApplication *)application {    // load xml file as text    NSString* path = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"xml"];    NSString* fileText = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];    NSLog(@"path:%d , fileText:%d",[path retainCount],[fileText retainCount]);    // parse text as xml    NSError* error;    GDataXMLDocument* document = [[GDataXMLDocument alloc] initWithXMLString:fileText options:0 error:&error];    GDataXMLElement *rootNode = [document rootElement];    // get user names by xpath    int count = 0;    NSArray* userList = [rootNode nodesForXPath:@"//users/user/name" error:&error];    for(GDataXMLNode* node in userList) {        NSLog([node stringValue]);    }    // Configure and show the window    [window addSubview:[navigationController view]];    [window makeKeyAndVisible];    [document release];}

    TouchXML

    TouchXML与上面的Google Data的XML解析器类似,也是基于libxml2的一款第三方DOM解析器。设置是一样的。

    下面开一个例子(从网上摘抄的):

    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
    #pragma mark -#pragma mark NewCateBooksViewController//将xml字符串中的某些元素解析到一个数组中+ (NSMutableArray*) parseBooks: (NSString*)xmlString /* NewCateBooksViewController */{     if(0 == [xmlString length])     return nil;     NSMutableArray* items = [[[NSMutableArray alloc] init] autorelease];     CXMLDocument *doc = [[CXMLDocument alloc] initWithXMLString: xmlString options: 0 error: nil];     NSArray *resultNodes = nil;     resultNodes = [doc nodesForXPath:@"//booklist" error:nil];//根结点     if([resultNodes count])     {          CXMLElement *rootElement = [resultNodes lastObject];          if(rootElement)          {               NSArray* _bookElements = [rootElement elementsForName:@"book"];               for(CXMLElement* _bookElement in _bookElements)               {                    RecomendBookListBean * bean = [[RecomendBookListBean alloc] init];                    // if([_cateElements count])                    // bean.b_cate_name = [[_cateElements lastObject] stringValue];                    // bean.b_id = [_bookElement elementsForName:@"id"];                    NSArray * idElements = [_bookElement elementsForName:@"id"];                    if([idElements_ count])                         bean.book_id=[[idElements_ lastObject]stringValue];                    NSArray* nameElements = [_bookElement elementsForName:@"name"];                    if([nameElements count])                         bean.book_name = [[nameElements lastObject] stringValue];                    NSArray* authorElements = [_bookElement elementsForName:@"author"];                    if([authorElements count])                         bean.book_author= [[authorElements lastObject] stringValue];                    NSArray* urlElements = [_bookElement elementsForName:@"bookcoverurl"];                    if([urlElements count])                         bean.book_pic_url= [[urlElements lastObject] stringValue];                    NSArray* descripElements = [_bookElement elementsForName:@"description"];                    if([descripElements count])                         bean.book_description = [[descripElements lastObject] stringValue];                    NSArray* sizeElements = [_bookElement elementsForName:@"size"];                    if([sizeElements count])                             bean.book_size = [[sizeElements lastObject] stringValue];                    [items addObject: bean];                    [bean release];               }          }      }     [doc release];     return items;}#pragma mark --(void)updateArray:(NSString *)Url{     NSError *error;     NSURLResponse *response;     NSData *dataReply;     NSString *stringReply;     NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:[NSURL URLWithString:Url]];     [request setHTTPMethod:@"GET"];     dataReply = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];     if(dataReply==nil&&error!=nil)     {          return;     }     else     {          stringReply = [[NSString alloc]initWithData:dataReply encoding:NSUTF8StringEncoding];          [bookArray addObjectsFromArray:[xmlTry parseBooks:stringReply]]; //调用解析函数          [stringReply release];//remember to release     }}

    KissXML

    KissXML据说速度比 TouchXML 快些,暂时还没有试过,用兴趣的朋友可以试试。例子如下:

    123456789101112131415161718192021222324
    DDXMLDocument *doc = [[[DDXMLDocument alloc] initWithData:data options:0 error:&error] autorelease];DDXMLElement *root = [doc rootElement];[root addNamespace:[DDXMLNode namespaceWithName:@"idx" stringValue:@"urn:atom-extension:indexing"]];[root addNamespace:[DDXMLNode namespaceWithName:@"gr" stringValue:@"http://www.google.com/schemas/reader/atom/"]];[root addNamespace:[DDXMLNode namespaceWithName:@"media" stringValue:@"http://search.yahoo.com/mrss/"]];[root addNamespace:[DDXMLNode namespaceWithName:@"foo" stringValue:@"http://www.w3.org/2005/Atom"]];NSArray *titles = [root nodesForXPath:@"//foo:feed/foo:title" error:&error];NSArray *feedTitles = [root nodesForXPath:@"//foo:source/foo:title" error:&error];NSArray *feedIds = [root nodesForXPath:@"//foo:source/foo:id" error:&error];NSArray *entryTitles = [root nodesForXPath:@"//foo:entry/foo:title" error:&error];NSArray *contents = [root nodesForXPath:@"//foo:entry/foo:content" error:&error];NSArray *publisheds = [root nodesForXPath:@"//foo:entry/foo:published" error:&error];for (NSUInteger i = 0; i < [feedTitles count]; i++) {NSMutableDictionary *result = [[[NSMutableDictionary alloc] init] autorelease];[result setObject:[[feedIds objectAtIndex:i] stringValue] forKey:@"feed_id"];[result setObject:[[feedTitles objectAtIndex:i] stringValue] forKey:@"feed_title"];[result setObject:[[entryTitles objectAtIndex:i] stringValue] forKey:@"entry_title"];[result setObject:[[contents objectAtIndex:i] stringValue] forKey:@"content"];[result setObject:[[publisheds objectAtIndex:i] stringValue] forKey:@"published"];    [self.objects addObject:result];}