网络数据的XML解析
XML解析一般分兩種模式SAX和DOM,事件和文檔。具體解析google去吧,有詳細(xì)。不過看了下面的兩個(gè)例子,一般就了解了。
一:XML解析之SAX解析,以及對(duì)NSXMLParser的應(yīng)用。
sax解析說白了,就是一個(gè)事物模型解析,從頭開始讀取文檔然后根據(jù)讀取到的頭標(biāo)簽標(biāo)簽時(shí)要怎么處理,讀完頭標(biāo)簽后,理論上是讀取標(biāo)簽值了,
然后讀取后遇到結(jié)束標(biāo)簽等
SDK本身是提供了NSXMLParser解析器。
1 -(BOOL)parser:(NSString*)string 2 { 3 //系統(tǒng)自帶的 4 NSXMLParser *par = [[[NSXMLParser alloc] initWithData:[string dataUsingEncoding:NSUTF8StringEncoding]]autorelease]; 5 //設(shè)置NSXMLParser對(duì)象的解析方法代理 6 [par setDelegate:self]; 7 //調(diào)用代理解析NSXMLParser對(duì)象,看解析是否成功 8 return [par parse]; 9 } 10 11 #pragma mark xmlparser 12 //step 1 :準(zhǔn)備解析 13 - (void)parserDidStartDocument:(NSXMLParser *)parser 14 { 15 // NSLog(@"%@",NSStringFromSelector(_cmd) ); 16 } 17 //step 2:準(zhǔn)備解析節(jié)點(diǎn) 18 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 19 { 20 // NSLog(@"%@",NSStringFromSelector(_cmd) ); 21 } 22 //step 3:獲取首尾節(jié)點(diǎn)間內(nèi)容 23 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 24 { 25 NSLog(@"%@",NSStringFromSelector(_cmd) ); 26 } 27 28 //step 4 :解析完當(dāng)前節(jié)點(diǎn) 29 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 30 { 31 NSLog(@"%@",NSStringFromSelector(_cmd) ); 32 } 33 34 //step 5;解析結(jié)束 35 - (void)parserDidEndDocument:(NSXMLParser *)parser 36 { 37 // NSLog(@"%@",NSStringFromSelector(_cmd) ); 38 } 39 //獲取cdata塊數(shù)據(jù) 40 - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock 41 { 42 // NSLog(@"%@",NSStringFromSelector(_cmd) ); 43 }1.初始化解析器,傳入你要解析的數(shù)據(jù)。
2.parse,啟動(dòng)解析,返回一個(gè)是否解析成功Bool值。
3.基本你要處理的就在下面實(shí)現(xiàn)的1-5個(gè)代理方法了。
其實(shí)代理方法和詳細(xì),就是一個(gè)事物進(jìn)行流程:
step1是準(zhǔn)備解析,然后沒意外就是執(zhí)行到了——>
step2讀取到第一個(gè)頭節(jié)點(diǎn)了,然后如果內(nèi)部有屬性值,你可以獲取出來,讀完頭節(jié)點(diǎn),我們會(huì)進(jìn)去值域——>
step3對(duì)于簡(jiǎn)單的節(jié)點(diǎn),可能直接就是一個(gè)string值了,但是看例子我們會(huì)知道,很多情況下,該節(jié)點(diǎn)的值域包含的于是一個(gè)節(jié)點(diǎn)——>
這步其實(shí)分兩種,如果是值,那么就是執(zhí)行step4,獲取值的字竄,如果是子節(jié)點(diǎn)呢,我們一看就知道,它又是進(jìn)行了step2,
即讀取到頭標(biāo)簽了,其實(shí)你是很人讀一片文章流程一樣,只不過我們腦中有個(gè)印象<xxx>是頭標(biāo)簽了,我們要做什么,獨(dú)到 頭標(biāo)簽的最后一個(gè)符號(hào)">"
下面進(jìn)去值域,獨(dú)到了字竄的話就調(diào)用了foundCharacters:(NSString *)string,如果又讀到<xxx>這樣的,那就又是頭標(biāo)簽了。——>
step5就是讀到開始尾標(biāo)簽符號(hào)了。
最后一個(gè)方法
foundCDATA:(NSData *)CDATABlock,其實(shí)也是一個(gè)格式
<content:encoded> <![CDATA[ <img src="http://img1.douban.com/mpic/s10489201.jpg" style="float:right;margin-left:16px"/><a href="http://www.douban.com/people/maldini/">減卐肥?</a>評(píng)論: <a href="http://movie.douban.com/subject/6799191//">搜索</a><br/> <br/>評(píng)價(jià): 力薦<br/><br/> ]]> </content:encoded>好了,方法和流程大致了解了,拿一個(gè)我最近遇到的例子,好多時(shí)候,我們會(huì)遇到這樣讀取一組類似于json中數(shù)組形式的數(shù)據(jù)
<channel> <title>我是標(biāo)題</title> <link>http://write.blog.csdn.net/postedit</link> <description>...</description> <language>zh-cn</language> <pubDate>Fri, 03 Aug 2012 06:20:31 GMT</pubDate> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> <item>...</item> </channel> 一般來說,我們要的數(shù)據(jù)其實(shí)都是這20個(gè)item,對(duì)吧,每個(gè)item下都是相同的3個(gè)標(biāo)簽,title,author,time。形式上 其實(shí)一種數(shù)組形式 那么要怎么解析呢 1,首先我們可能先申明一個(gè)array數(shù)組容器用來存放這個(gè)20個(gè)對(duì)象,然后每個(gè)item對(duì)象中又有3個(gè)元素,那么我們可以 考慮用一個(gè)字典數(shù)據(jù)結(jié)構(gòu)來表示每個(gè)item。 2.需要至少申請(qǐng)兩個(gè)空間來作為類似于“哨兵”存儲(chǔ)當(dāng)前執(zhí)行到的節(jié)點(diǎn)名,以及節(jié)點(diǎn)的值。 3.然后每次執(zhí)行到讀取到item時(shí),初始化我們上面說道的一個(gè)字典數(shù)據(jù)結(jié)構(gòu)。 4.在foundCharacters:方法中一直保存當(dāng)前最新的值(當(dāng)然,這里面其實(shí)會(huì)有個(gè)小瑕疵,下面會(huì)說到)。 5.在標(biāo)簽結(jié)束的方法,我們把標(biāo)簽名和值已鍵值對(duì)存入上面初始化的字典容器中。 1 #pragma mark xmlparser 2 //step 1 :準(zhǔn)備解析 3 - (void)parserDidStartDocument:(NSXMLParser *)parser 4 { 5 // NSLog(@"%@",NSStringFromSelector(_cmd) ); 6 7 parserObjects = [[NSMutableArray alloc]init]; 8 } 9 //step 2:準(zhǔn)備解析節(jié)點(diǎn) 10 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 11 { 12 // NSLog(@"%@",NSStringFromSelector(_cmd) ); 13 14 self.currentText = [[NSMutableString alloc]init]; 15 [currentText release]; 16 if ([elementName isEqualToString:@"item"]) { 17 NSMutableDictionary *newNode = [[ NSMutableDictionary alloc ] initWithCapacity : 0 ]; 18 twitterDic = newNode; 19 [parserObjects addObject :newNode]; 20 [newNode release]; 21 } 22 else if(twitterDic) { 23 NSMutableString *string = [[ NSMutableString alloc ] initWithCapacity : 0 ]; 24 [twitterDic setObject :string forKey :elementName]; 25 [string release ]; 26 currentElementName = elementName; 27 } 28 29 30 } 31 //step 3:獲取首尾節(jié)點(diǎn)間內(nèi)容 32 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 33 { 34 NSLog(@"%@",NSStringFromSelector(_cmd) ); 35 [currentText appendString:string]; 36 } 37 38 //step 4 :解析完當(dāng)前節(jié)點(diǎn) 39 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 40 { 41 if ([elementName isEqualToString:@"item"]) { 42 twitterDic = nil; 43 }else 44 if ([elementName isEqualToString:currentElementName]) { 45 46 if ([elementName isEqualToString:@"description"] 47 ||[elementName isEqualToString:@"content:encoded"]) { 48 [twitterDic setObject:Cdata forKey:currentElementName]; 49 }else { 50 [twitterDic setObject:currentText forKey:currentElementName]; 51 } 52 } 53 54 } 55 56 //step 5;解析結(jié)束 57 - (void)parserDidEndDocument:(NSXMLParser *)parser 58 { 59 } 60 //獲取cdata塊數(shù)據(jù) 61 - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock 62 { 63 Cdata =[[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding]; 64 } 二:Dom文檔解析模型,TBXML第三方包應(yīng)用。 dom解析模型就像一個(gè)樹結(jié)構(gòu),節(jié)點(diǎn),子節(jié)點(diǎn),兄弟節(jié)點(diǎn)等等。 這個(gè)其實(shí)最后被我拋棄了,這個(gè)解析器太簡(jiǎn)化了,太簡(jiǎn)潔的東西導(dǎo)致控制的入口點(diǎn)太少,就比如一個(gè)一鍵優(yōu)化的軟件的概念是一樣的,一鍵清楚緩存,優(yōu)化配置,文件歸類等等。人為控制就少了,導(dǎo)致我解析上面那個(gè)模型時(shí),只知道遍歷存儲(chǔ)~。但是這個(gè)解析期對(duì)部分要求不高的xml解析其實(shí)挺好分,真的很簡(jiǎn)潔。 1 - (void)recurrence:(TBXMLElement *)element { 2 3 NSString *eleName = [TBXML elementName:element]; 4 NSString *eleText = [TBXML textForElement:element]; 5 if ([eleName isEqualToString:@"item"]) { 6 self recurrence:element 7 } 8 do { 9 10 NSString *eleName = [TBXML elementName:element]; 11 NSString *eleText = [TBXML textForElement:element]; 12 13 //遞歸處理子樹 14 if (element->firstChild) { 15 NSLog(@"<%@>:",eleName);// Display the name of the element 16 17 [self recurrence:element->firstChild]; 18 }else { 19 NSLog(@"<%@>:%@",eleName,eleText);// Display the name of the element 20 21 TBXMLElement *parent = element->parentElement; 22 if ([[TBXML elementName:parent] isEqualToString:@"item"]) { 23 NLRssInfo *info = [[[NLRssInfo alloc]init] autorelease]; 24 25 if ([eleName isEqualToString:@"title"]) { 26 info.title = eleText; 27 } 28 29 [dataArr addObject:info]; 30 } 31 32 } 33 34 //迭代處理兄弟樹 35 } while ((element = element->nextSibling)); 36 } 37 38 - (void) dealloc 39 { 40 [title release]; 41 [subtitle release]; 42 [super dealloc]; 43 } 遞歸遍歷,常規(guī)的樹操作,具體內(nèi)容可以網(wǎng)上搜搜,很多。 并且開源庫(kù)的好處就是有源代碼,也就3個(gè)類,6個(gè)文件,有興趣可以研究研究,貌似大部分代碼是用C寫的。?
轉(zhuǎn)載于:https://www.cnblogs.com/tryingx/articles/3715243.html
總結(jié)
以上是生活随笔為你收集整理的网络数据的XML解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring MVC 中的 forwar
- 下一篇: 通过微软的cors类库,让ASP.NET