NSXMLParser详细案例

距离过年了,越来也就越懒了。
本周带来的是SDK自带的NSXMLParser的详细案例。
可以用于解析XML。关于XML,这裡先脑补下。

本次参考资料:
https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/Classes/NSXMLParser_Class/Reference/Reference.html

XML:
可扩展标记语言,是一种标记语言。
标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种信息的文章等。
如何定义这些标记,既可以选择国际通用的标记语言,比如HTML,也可以使用像XML这样由相关人士自由决定的标记语言,这就是语言的可扩展性。
XML是从标淮通用标记语言中简化修改出来的。它主要用到的有可扩展标记语言、可扩展样式语言、XBRL和XPath等。

好吧,我可以说我在偷懒,随便 维基百科 copy过来的…
详细内容,请浏览维基百科:http://zh.wikipedia.org/zh-hk/XML

接著回到NSXMLParser,是SAX模式解析XML。
而XML解析一般分为SAX和DOM,
前者是事件驱动在xml中寻找特定条件的内容,提取需要内容,好处就是佔用内存小,灵活。
缺点是存取整份XML的时候,SAX则会显得特别麻烦。
后者是文档对象,原理是将整个XML一次读出,放在树型结构里面,需要的时候则查找对应节点。
好处就是简单,缺点就是占内存啦,
关于SAX可以参考维基百科:http://zh.wikipedia.org/zh-hk/SAX
如有兴趣后面将收集资料,再详细说下这2者。

进入正题,先创建XML和NSXMLParser
[objc]
//为了方便看,所以酱紫写咯。
NSString *xmlString =[NSString stringWithFormat:
@"<Body>"
"<xml1>Test</xml1>"
"<xml2 id=\"001\">"
"<xml3>kumadocs.com</xml3>"
"</xml2>"
"</Body>"];
NSLog(@"%@",xmlString);//为了方便查看,我们再输出出来
NSData *data=[NSData dataWithBytes:[xmlString UTF8String] length:[xmlString length]];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; //设置XML数据,当然还有initWithContentsOfURL:可以用
[parser setDelegate:self];//设置Delegate,如果不想有烦人的黄色感叹号,记得在头文件中加入 NSXMLParserDelegate 协议
if ([parser parse]) {//启动解析
//返回 YES 则解析成功
NSLog(@"Returns YES in the event of a successful parse.");
}else{
//返回 NO 则解析有误
NSLog(@"Returns NO in case of error.");
}
[/objc]

NSXMLParser解析工作是靠它的5个委託(NSXMLParserDelegate)来实现的。
为了不导致场面那麽混乱,我们直接简单的在控制台输出
[objc]
////////////////////

– (void)parserDidStartDocument:(NSXMLParser *)parser
{
//准备解析
NSLog(@"sent when the parser begins parsing of the document.");

}

– (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
//遍例xml的节点 显示元素符
NSLog(@"SName : %@",elementName);

//元素符 中包含 属性
if ( attributeDict.count ){
NSLog(@"%@ = %@",elementName,attributeDict);
}

//一般情况下,在这裡我们会进行判断
//元素是否为需要的,如需要会初始化并创建 动态字典/数组/字符串

}

– (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
//当xml节点有值时,则进入此句 处理包含标籤内容
NSLog(@"Value : %@",string);

//在此处,我们会将 值 存入以创建好的 动态字典/数组/字符串 中
}

– (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
//当遇到结束符号’/’时,进入此句
NSLog(@"EName : %@",elementName);

//在此处,会进行清除临时存储的 动态字典/数组/字符串

}

– (void)parserDidEndDocument:(NSXMLParser *)parser
{
//解析结束,如果到这裡已经是代表解析成功
NSLog(@"sent when the parser has completed parsing. ");
}

////////////////////
[/objc]

下面我们看到,控制台输出如下:
1.进入parserDidStartDocument:准备解析
2.进入didStartElement: 读取第一个节点,此时内部没有值所以不会输出。
3.由于Body下是有子节点,此时会继续进入didStartElement:
4.再读取xml1,读取完xml1后,则进入foundCharacters:获取值
5.此时遇到尾标籤符号进入didEndElement:,结束xml1。
6.再次进入didStartElement:,由于xml2.是有内部值,所以会输出一个Dictionary。
7….无限循环著didStartElement: \ foundCharacters: \ didStartElement: …
8.最后来到parserDidEndDocument:,也就是到了这裡代表了解析结束,也代表了解析成功。
9.此时[parser parse]就会返回出YES 或者 NO。
[objc]
2014-01-06 15:44:40.795 test[6242:60b] <Body><xml1>Test</xml1><xml2 id="001"><xml3>kumadocs.com</xml3></xml2></Body>
2014-01-06 15:44:40.799 test[6242:60b] sent when the parser begins parsing of the document.
2014-01-06 15:44:40.800 test[6242:60b] SName : Body
2014-01-06 15:44:40.802 test[6242:60b] SName : xml1
2014-01-06 15:44:40.803 test[6242:60b] Value : Test
2014-01-06 15:44:40.805 test[6242:60b] EName : xml1
2014-01-06 15:44:40.807 test[6242:60b] SName : xml2
2014-01-06 15:44:40.808 test[6242:60b] xml2 = {
id = 001;
}
2014-01-06 15:44:40.810 test[6242:60b] SName : xml3
2014-01-06 15:44:40.811 test[6242:60b] Value : kumadocs.com
2014-01-06 15:44:40.813 test[6242:60b] EName : xml3
2014-01-06 15:44:40.814 test[6242:60b] EName : xml2
2014-01-06 15:44:40.816 test[6242:60b] EName : Body
2014-01-06 15:44:40.817 test[6242:60b] sent when the parser has completed parsing.
2014-01-06 15:44:40.818 test[6242:60b] Returns YES in the event of a successful parse.

[/objc]

看了上面那堆,基本方法和流程算是清楚了。
但在实际运用中,一般我们都是在didStartElement:中进行判断。
判断是否为我们需要的节点,如果是,则初始化一个 动态数组。
而在foundCharacters:则存入值,
最后在didStartElement:清除临时存储的数据。

总觉得是在草草收尾,下次还是XML解析,只不过是DOM方式。

81 thoughts on “NSXMLParser详细案例

Qklxvh进行回复 取消回复

电子邮件地址不会被公开。