iPhone开发技巧之网络篇(1)--- 解析XML
2011-05-17 21:49
435 查看
开发 iPhone 上的网络应用程序的时候时常需要解析XML文档,比如web应用中的SOAP,REST,RSS信息等都是以XML为基础的。掌握XML解析的技术是很重要的。这里我将为大家介绍一下iPhone下解析XML的几种方法,并比较其性能。
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的解析器有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文档还是值得一用的。)
相同的XML文档由网络下载,然后解析,比较的结果如下 :
可以看到,libxml2比NSXMLParser快得多。这与它们处理的方式有些关系,NSXMLParser中调用SAX API的时候,参数是作为字符串传递的,需要先转换为NSString或者是NSDictionary对象,并且它不像libxml2那样是一边下载一边解析,需要整个文件下载完了才开始解析。所以说建议一般使用libxml2。
代码如下:
实际使用的时候除最后两行以外,所有的当如一个类中,最后两个是启动该类的代码。
首先需要将libxml添加到你的工程项目中。
我们知道,当向项目中添加外部库的时候,如果是程序框架的,比如UIKit.framework,Foundation.framework等放在Sysytem/Library/Frameworks 目录下。SDK放在 /Developer/Platforms/iPhoneOS.platform/Developer/SDKs 目录下。
但是由于libxml是UNIX的库、位于SDK文件夹的usr/lib下。头文件位于 usr/include 下。
在 libxml 目录下将 libxml2.2.dylib(或更高版本)添加到项目中。将头文件路径 usr/include/libxml2 也添加到包含路径中。
libxml中的SAX解析器
用过SAX解析器的朋友都知道,SAX就是事先登录一些处理函数,当XML解析到属性或要素的时候,回调登录的处理函数。
以下是一个例子,DownloadOperation实现网络文件的下载,同时交给libxml2的SAX解析器处理:
首先、#import了libxml/tree.h头文件。然后声明了一个 xmlParserCtxtPtr 变量作为解析器的实例。
连接开始的时候(start函数)使用 xmlCreatePushParserCtxt 创建解析器实例,这里注意第二个参数,将DownloadOperation 的实例传到解析器内,这个正是回调函数中的第一个参数 — 作为回调函数的句柄调用类成员函数(当然,不使用实例方法,将回调函数设置成类方法也是可行的。但是当你使用到DownloadOperation中的成员等会有些不便,所以从OO的角度出发,还是传递回调函数的对象实例为佳)。
开始下载的时候,因为数据是顺序得到的,所以一边下载,一边用 xmlParseChunk 传递给解析器。
libxml的SAX句柄函数在xmlSAXHandler结构中定义。这个构造体内有30多个句柄定义,一般我们只需要登录其中几个就够了。比如例子中的 startElementNsSAX2Func、endElementNsSAX2Func、charactersSAXFunc 等,他们的定义如下:
最后,因为用SAX解析,需要知道当前解析的位置,所以标记参数需要合理的使用。
使用的时候,先从这里下载并解冻 Google Data APIs Objective-C Client Library,然后将下面解开的文件拷贝到项目中去。
解析的例子如下:
下面就是使用方法了,DOM的API使用起来还是感觉便利些:
下面开一个例子(从网上摘抄的):
说到XML不得不提WEB应用中最常见的几种通讯规范:SOAP,XML-RPC,WSDL等,他们都是基于XML协定的。在下一节中我将介绍几种处理web应用的程序库。
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文档由网络下载,然后解析,比较的结果如下 :
下载用时 | 解析用时 | 合计 | |
---|---|---|---|
NSXMLParser | 1.419s | 5.525s | 7.134s |
libxml2 | 2.520s | 2.247s | 2.646s |
NSXMLParser的例子
解析的XML代码例子如下:1 2 3 4 5 | <?xml version="1.0" encoding="UTF-8"?> <users> <user name="hoge" age="20" /> <user name="fuga" age="30" /> </users> |
1 2 3 4 56 | 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 下。
在 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
libxml中的SAX解析器
用过SAX解析器的朋友都知道,SAX就是事先登录一些处理函数,当XML解析到属性或要素的时候,回调登录的处理函数。
以下是一个例子,DownloadOperation实现网络文件的下载,同时交给libxml2的SAX解析器处理:
1 2 3 4 56 | // 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 |
1 2 3 4 56 | // 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; @end static 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 |
开始下载的时候,因为数据是顺序得到的,所以一边下载,一边用 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,然后将下面解开的文件拷贝到项目中去。
1 2 3 4 | GDataXMLNode.h GDataXMLNode.m GDataDefines.h GDataTargetNamespace.h |
1 2 3 4 56 | <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> |
1 2 3 4 56 | #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解析器。设置是一样的。下面开一个例子(从网上摘抄的):
1 2 3 4 56 | #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 快些,暂时还没有试过,用兴趣的朋友可以试试。例子如下:1 2 3 4 56 | 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]; } |
相关文章推荐
- iPhone开发技巧之网络篇(1)--- 解析XML
- iPhone开发技巧之网络篇(1)— 解析XML
- iPhone开发技巧之网络篇(1)— 解析XML
- iPhone开发技巧之网络篇(1)— 解析XML A
- iPhone/iPad 开发: 解析本地/网络上的xml文件
- iPhone/iPad 开发: 解析本地/网络上的xml文件
- iPhone开发 解析xml NSData
- iOS开发之网络数据解析(二)--XML解析简介
- Objective-C ,ios,iphone开发基础:使用GDataXML解析XML文档,(libxml/tree.h not found 错误解决方案)
- iPhone开发 解析xml NSData xml
- iphone基于网络的客户端开发技巧——后台上传
- iOS开发之网络编程篇四:XML,JSon解析
- iPhone开发 解析xml NSData
- iPhone/iPad 开发: 解析本地/网络上的xml文件
- iPhone开发 NSXMLParser解析xml文件
- Iphone开发之xml解析流程小结
- iphone开发之iphone解析xml&json-2
- iphone开发之iphone解析xml&json-1
- iphone开发之使用touchXml解析xml并且存储到SQLite中
- iPhone开发笔记——webservice解析xml