转载:http://www.jianshu.com/p/5c8af49f31f8
一、概念
1、XML概念:
Extensible Markup Language(可扩展标记语言)
HTML (超文本标记语言)
非常类似于HTML,HTML的作用是显示数据,XML的目的是存储和传输数据
XML是以前各种应用之间传输数据最常用的格式
W3C的推荐标准
2、语法
<Class className="三年一班">
<Person color="yellow" weight="130" height="150">
<name>wg</name>
<age>108</age>
</Person>
<Student name="y" />
</Class>
(1)有且只能有一个根节点!!!根节点就是最外面的那个标签,Class就是根节点
(2)注释: <!-- 我是注释 -->
(3)可以添加一个属性后直接结束 <Student name="y" />
二、XML解析SAM方式(只读)
XML格式的解析方式
SAX :iOS上解析,速度快,内存占用小,只读
DOM : mac上的解析方式,iOS无法直接使用,解析过程中内存占用大,读写
SAX的解析步骤:
例子:解析XML文档到模型中
注意:KVC的所有属性要用copy,不然拼接字符串会导致模型的值为空(因为KVC只是改变指针指向,而不是赋值)
@property (nonatomic,strong) NSMutableArray *videos;(懒加载)
//当前创建的video对象
strong) Video *currentVideo;
//存储当前节点的内容
copy) NSMutableString *mString;(懒加载)
1.加载数据
//解析数据
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
//设置代理
parser.delegate = self;
//开始执行代理的方法,代理的方法中开始解析的
[parser parse];
2.实现代理方法:
(1)开始解析文档时执行
- (void)parserDidStartDocument:(NSXMLParser *)parser {
}
(2)找开始节点时执行
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict {
//如果是video标签,创建video对象
if ([elementName isEqualToString:@"video"]) {
self.currentVideo = [[Video alloc] init];
self.currentVideo.videoId = @([attributeDict[@"videoId"] intValue]);
//添加到数组中
[self.videos addObject:self.currentVideo];
}
}
3.找节点之间的内容时执行
void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
//拼接字符串
[self.mString appendString:string];
}
(4)找结束节点时执行
didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
//判断标签是否是对应的属性
if (![elementName isEqualToString:@"video"] && ![elementName "videos"]) {
//self.currentVideo.length =
//kvc 赋值的过程就是地址指向的过程,不会做类型转换
[self.currentVideo setValue:self.mString forKey:elementName];
}
//清空可变字符串
[self.mString setString:@""];
}
(5)结束解析文档时执行
void)parserDidEndDocument:(NSXMLParser *)parser {
NSLog(@"%@",0)">self.videos);
}
(6)解析出错时执行
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
}
三、DOM方式解析(可读写)
DOM方式的解析 Document Object Model
DOM--文档对象模型(文档树模型)
一次性把xml全部加载到内存,内存消耗大
之前的SAX方式只能读取XML,DOM可以修改,添加删除修改节点
iOS默认不支持DOM解析(不支持NSXML这个类),在iOS解析DOM的话需要第三方框架:GData/KissXML(XMPP中使用此框架)
适合读写比较小的XML文件
GData项目地址:https://github.com/graetzer/GDataXML-HTML
GData第三方框架使用:
(1)搜索Header Search Paths
复制路径添加到这里 /usr/include/libxml2
(2)添加标识
搜索 Other Linker Flags ,复制 -lxml2 添加到这里
概念:
节点Node:XML中所有内容都是节点,包括标签、属性、注释、文本内容等。
元素Element:表示一个标签,包括标签本身(标签名字和标签内容(内容可能是子标签))和标签的属性(属性名字和属性内容),Element继承于Node
框架中的三个类:
GdataxMLDocument
GdataxMLNode
GdataxMLElement
使用步骤:XML解析转模型方法
1.加载XML数据到GdataxMLDocument对象中
GdataxMLDocument *document = [[GdataxMLDocument alloc] initWithData:data error:NULL];
2.获取xml文档的根元素(根元素包括videos标签内的所有内容,即XML的所有内容)
GdataxMLElement *rootElement = document.rootElement;
3、遍历二级video节点
NSMutableArray *mArray = [NSMutableArrayarrayWithCapacity:10];
//遍历所有的video节点
for (GdataxMLElement *element in rootElement.children) {
//创建一个模型对象,添加到模型数组中
Video *v = [[Video alloc] init];
[mArray addObject:v];
//遍历每个video的子标签
for (GdataxMLElement *subElement in element.children) {
//给模型KVC赋值
[v setValue:subElement.stringValue forKey:subElement.name];
}
//遍历video的所有属性(包括video标签自己的属性)
for (GdataxMLNode *attr in element.attributes) {
[v setValue:attr.stringValue forKey:attr.name];
}
}
NSLog(@"%@",mArray);
四、GData写入功能,生成XML
该功能可将原生文本输入转换为HTML,例如下面面试小demo(有空再上传):
使用方法:
// 创建一个标签元素
GdataxMLElement *element = [GdataxMLNode elementWithName:@"user" stringValue:@"will"];
// 创建一个属性
GdataxMLElement *attribute = [GdataxMLNode attributeWithName:@"a" "b"];
// 创建一个根标签
GdataxMLElement *rootElement = [GdataxMLNode "root"];
// 把标签与属性添加到根标签中
[rootElement addChild:element];
[rootElement addAttribute:attribute];
// 生成xml文件内容
GdataxMLDocument *xmlDoc = [[GdataxMLDocument alloc] initWithRootElement:rootElement];
NSData *data = [xmlDoc XMLData];
NSString *xmlString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@NSLog输出为:
<?xml version="1.0"?>
<root a="b"><user>will</user></root>