您的位置:首页 > 理论基础 > 计算机网络

iOS开发之网络编程:XML,JSon解析

2016-04-09 09:26 579 查看


一、XML和JSon是什么

XML

下面是一段XML文本:





大家可以看看,有什么特点。

好了,我就不卖关子了,第一行介绍XML的版本和编码格式。

下面就是一个个形如<></>而且都是成对出现的,这个叫做标签。<>这是开标签,</>这是关标签。要获取某个标签的数据,需要一步步遍历下去,直到找到你所需要的那个标签下的内容,比如我要获取老师晁辉的年龄<teacher></teacher>里,那我先找到开标签为teacher的,然后找第一个面的名字是不是晁辉,不是那我就直接到第二个teacher,直到第三个teacher是叫晁辉,那我再找第三个teacher下的子标签的开标签为<age>的,那这个age的内容就是我们所需的晁辉的年龄。是不是觉得真特么麻烦??对的。这是没办法的事,XML就是这么不爽,所以如果你们公司的后台给你的数据就是一堆XML,那恭喜你了。
JSon

那JSon长什么样呢??机智的少年,直接就会回到前两篇,找到咱们获取数据的那个URL,将这个可爱的URL,拷贝到你的浏览器的地址栏,前往,你就看到长长的可爱的JSon数据(因为咱们之前做的一直是JSon解析啊!!!)。

我截取了部分数据:





 

是不是觉得里面的数据很眼熟??对的,一个大括号里面对应一个dictionary,一个中括号对应一个array。就这么点。那我问你,要找dictionary和array里面的对应数据容易不容易??遍历起来方不方便(大声告诉我!),所以啊,拿到JSon数据,你应该放声大笑。下面XML会用代码教你们做人~~~


二、解析XML

XML解析又有sax和DOM解析之分,前一个是逐行解析,文件损坏对解析没影响,但是就和我上面和大家介绍的一样,需要一个一个标签去读,读到你崩溃为止。后一个一个是完全读入整个文件,简单粗暴。但是文件一旦有某个位置错误,就GG了,而且灰常消耗内存。所以啊,都不好用,但非得用。
sax解析

先遵守NSXMLParserDelegate协议。
    // 读入文件
NSString *path = [[NSBundle mainBundle] pathForResource:@"teacher" ofType:@"xml"];

// NSXMLParser对象
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:[NSData dataWithContentsOfFile:path]];

// 设置delegate对象(解析过程放在代理中执行)
parser.delegate = self;

// 执行解析
[parser parse];

代理方法里面进行逐行解析:
// 开始标签
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSLog(@"%@", elementName);
}
 
// 结束标签
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
NSLog(@"%@", elementName);
}
 
// 取值
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
NSLog(@"%@", string);
}

注意:sax解析是系统提供的一套解析方案,sax解析的优点:逐行解析,不会一次性读入整个文件,减小内存消耗。因为是逐行解析,xml文件损坏对解析没影响;sax解析的缺点:因为是逐行解析,所以没办法获取文件的层级关系,对于程序员获取数据而言比较麻烦。
DOM解析

DOM解析需要引入两个文件。有兴趣自己动手的同学,需要注意。





就是上图的两个文件,拖进工程后,需要做三件事。













前两个是处理文件链接路径,下面一个是将MRC文件编译到ARC工程中所需的操作。

接下来上DOM解析代码:
/********************************DOM*******************************/
// 获取文件路径
NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];

NSError *error;
GDataXMLDocument *document = [[GDataXMLDocument alloc] initWithXMLString:str options:0 error:&error];

// 获取根节点
// 不断的找子节点来获取数据

GDataXMLElement *rootElement = document.rootElement;
NSLog(@"%@", rootElement);
// 获取子节点
NSArray *array = rootElement.children;
NSLog(@"%@", array[1]);

// 获取子节点的子节点
GDataXMLElement *childElement = array[1];
GDataXMLElement *element = childElement.children[1];
NSLog(@"%@", element);
NSString *sex = element.stringValue;
NSLog(@"%@", sex);

上面就是拿到一个节点,然后找子节点,逐行找。。。

第二种,已知节点名字,找到节点内容:
/********************************DOM*******************************/
// 获取文件路径
NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSError *error;
GDataXMLDocument *document = [[GDataXMLDocument alloc] initWithXMLString:str options:0 error:&error];
// 第二种方式:使用elementForName:方法,给出一个节点的名字然后获取节点对应的数据
GDataXMLElement *rootelement = document.rootElement;
NSArray *arr = [rootelement elementsForName:@"teacher"];
NSLog(@"%@", arr[1]);
GDataXMLElement *element = arr[1];
GDataXMLElement *sex = [element elementsForName:@"sex"][0];
NSLog(@"%@", sex.stringValue);
 

第三种,绝对路径。
/********************************DOM*******************************/
// 获取文件路径
NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSError *error;
GDataXMLDocument *document = [[GDataXMLDocument alloc] initWithXMLString:str options:0 error:&error];
NSArray *array = [document nodesForXPath:@"teachers/teacher/sex" error:nil];
NSLog(@"%@", [array[1] stringValue]);

第四种,相对路径。
/********************************DOM*******************************/
// 获取文件路径
NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSError *error;
GDataXMLDocument *document = [[GDataXMLDocument alloc] initWithXMLString:str options:0 error:&error];
NSArray *array = [document nodesForXPath:@"//age" error:nil];
NSLog(@"%@", [array[2] stringValue]);

看到这里,是不是被恶心到了。。。


三、解析JSon

这个就非常简单了。一行代码搞定,拿到咱们的NSData,然后
NSError *newError = nil;
// 获取数据
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&newError];

第一个参数就是我们从服务器获取的data数据。第二个参数指的是你的容器类型,这是个枚举值。
typedef NS_OPTIONS(NSUInteger, NSJSONReadingOptions) {
NSJSONReadingMutableContainers = (1UL << 0), // 用NSDictionary或者NSArray接收,可变的mutable也是可以的。
NSJSONReadingMutableLeaves = (1UL << 1), // 用NSMutableString接收
NSJSONReadingAllowFragments = (1UL << 2) // 既不是NSDictionary也不是NSArray的实例
}

如果获取的数据的最外层是中括号(上面的截图里面最外层是大括号),那么这里用来接收数据的变量类型就不是NSDictionary而是NSArray了。


四、总结

从本节的篇幅就可以看到,JSon用起来不是一般的方便,而XML怎么用都不爽。这个也是没办法的,只有央求你们的后台不会丢给你XML的数据了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios 网络编程 json xml