网络数据的XML解析

  XML解析一般分两种模式SAX和DOM,事件和文档。具体解析google去吧,有详细。不过看了下面的两个例子,一般就了解了。

一:XML解析之SAX解析,以及对NSXMLParser的应用。

  sax解析说白了,就是一个事物模型解析,从头开始读取文档然后根据读取到的头标签标签时要怎么处理,读完头标签后,理论上是读取标签值了,

  然后读取后遇到结束标签等

  SDK本身是提供了NSXMLParser解析器。

 1 -(BOOL)parser:(NSString*)string  
 2 {  
 3     //系统自带的  
 4     NSXMLParser *par = [[[NSXMLParser alloc] initWithData:[string dataUsingEncoding:NSUTF8StringEncoding]]autorelease];  
 5     //设置NSXMLParser对象的解析方法代理
 6     [par setDelegate:self];
 7     //调用代理解析NSXMLParser对象,看解析是否成功
 8     return [par parse];   
 9 }    
10   
11 #pragma mark xmlparser  
12 //step 1 :准备解析  
13 - (void)parserDidStartDocument:(NSXMLParser *)parser  
14 {  
15 //    NSLog(@"%@",NSStringFromSelector(_cmd) );  
16 }  
17 //step 2:准备解析节点  
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:获取首尾节点间内容  
23 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string  
24 {  
25     NSLog(@"%@",NSStringFromSelector(_cmd) );  
26 }  
27   
28 //step 4 :解析完当前节点  
29 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName  
30 {  
31    NSLog(@"%@",NSStringFromSelector(_cmd) );  
32 }  
33   
34 //step 5;解析结束  
35 - (void)parserDidEndDocument:(NSXMLParser *)parser  
36 {  
37 //    NSLog(@"%@",NSStringFromSelector(_cmd) );  
38 }  
39 //获取cdata块数据  
40 - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock  
41 {  
42 //    NSLog(@"%@",NSStringFromSelector(_cmd) );  
43 }

1.初始化解析器,传入你要解析的数据。

2.parse,启动解析,返回一个是否解析成功Bool值。

3.基本你要处理的就在下面实现的1-5个代理方法了。

其实代理方法和详细,就是一个事物进行流程:

step1是准备解析,然后没意外就是执行到了——>

step2读取到第一个头节点了,然后如果内部有属性值,你可以获取出来,读完头节点,我们会进去值域——>

step3对于简单的节点,可能直接就是一个string值了,但是看例子我们会知道,很多情况下,该节点的值域包含的于是一个节点——>

  这步其实分两种,如果是值,那么就是执行step4,获取值的字窜,如果是子节点呢,我们一看就知道,它又是进行了step2,

  即读取到头标签了,其实你是很人读一片文章流程一样,只不过我们脑中有个印象<xxx>是头标签了,我们要做什么,独到 头标签的最后一个符号">"

  下面进去值域,独到了字窜的话就调用了foundCharacters:(NSString *)string,如果又读到<xxx>这样的,那就又是头标签了。——>

step5就是读到开始尾标签符号了。

  最后一个方法

  foundCDATA:(NSData *)CDATABlock,其实也是一个格式

<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>评论: <a href="http://movie.douban.com/subject/6799191//">搜索</a><br/> <br/>评价: 力荐<br/><br/> 
]]>  
</content:encoded>

  好了,方法和流程大致了解了,拿一个我最近遇到的例子,好多时候,我们会遇到这样读取一组类似于json中数组形式的数据

<channel>  
<title>我是标题</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> 
一般来说,我们要的数据其实都是这20个item,对吧,每个item下都是相同的3个标签,title,author,time。形式上
其实一种数组形式
那么要怎么解析呢
1,首先我们可能先申明一个array数组容器用来存放这个20个对象,然后每个item对象中又有3个元素,那么我们可以
考虑用一个字典数据结构来表示每个item。
2.需要至少申请两个空间来作为类似于“哨兵”存储当前执行到的节点名,以及节点的值。
3.然后每次执行到读取到item时,初始化我们上面说道的一个字典数据结构。
4.在foundCharacters:方法中一直保存当前最新的值(当然,这里面其实会有个小瑕疵,下面会说到)。
5.在标签结束的方法,我们把标签名和值已键值对存入上面初始化的字典容器中。
 1 #pragma mark xmlparser  
 2 //step 1 :准备解析  
 3 - (void)parserDidStartDocument:(NSXMLParser *)parser  
 4 {  
 5 //    NSLog(@"%@",NSStringFromSelector(_cmd) );  
 6       
 7     parserObjects = [[NSMutableArray alloc]init];  
 8 }  
 9 //step 2:准备解析节点  
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:获取首尾节点间内容  
32 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string  
33 {  
34     NSLog(@"%@",NSStringFromSelector(_cmd) );  
35     [currentText appendString:string];  
36 }  
37   
38 //step 4 :解析完当前节点  
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;解析结束  
57 - (void)parserDidEndDocument:(NSXMLParser *)parser  
58 {  
59 }  
60 //获取cdata块数据  
61 - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock  
62 {  
63     Cdata =[[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding];  
64 }
二:Dom文档解析模型,TBXML第三方包应用。
  dom解析模型就像一个树结构,节点,子节点,兄弟节点等等。
  这个其实最后被我抛弃了,这个解析器太简化了,太简洁的东西导致控制的入口点太少,就比如一个一键优化的软件的概念是一样的,一键清楚缓存,优化配置,文件归类等等。人为控制就少了,导致我解析上面那个模型时,只知道遍历存储~。但是这个解析期对部分要求不高的xml解析其实挺好分,真的很简洁。
 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 }
  递归遍历,常规的树操作,具体内容可以网上搜搜,很多。
  并且开源库的好处就是有源代码,也就3个类,6个文件,有兴趣可以研究研究,貌似大部分代码是用C写的。

 

posted @ 2014-05-08 00:12  激情为梦想而生  阅读(109)  评论(0编辑  收藏  举报