iOS应用数据存取的常用方式有如下几种
XML属性列表 —— PList
NSKeyedArchiver 归档
Preference(偏好设置)
SQLite3
Core Data
现在我想记录下项目中XML数据存储问题
XML 语法
- 一个常见的XML文档一般由以下部分组成
- 文档声明
- 元素
- 属性
- 在 XML 文档的最前面,必须编写一个文档声明,用来声明 XML文档的类型
- 例如:
<?xml version="1.0" ?>
- 用 encoding 属性说明文档的字符编码
<?xml version="1.0" encoding="UTF-8" ?>
元素:
-
一个元素包括了开始标签和结束标签
- 拥有内容的元素:
<item>NO1</item>
- 没有内容的元素:
<item></item>
- 没有内容的元素简写:
<item/>
- 拥有内容的元素:
一个元素可以嵌套若干个子元素(不能出现交叉嵌套)
<items>
<item>
<name>张三</name>
<length>20</length>
</item >
</items>
规范的 XML 文档最多只有1个根元素,其他元素都是根元素的子孙元素。
元素注意:
XML 中所有空格和换行,都会当做具体内容处理
下面两个元素的内容是不一样的:
这个没有空格<item>NO1</item>
这个中间有许多个\n,空格
< item>张三</item>
属性:
-
一个元素可以拥有多个属性
<item name="No 1"length="10"/>
- item 元素拥有name和length两个属性
- 属性值必须用双引号""或者单引号''扩住。
属性页可以用子元素来表示:
<item>
<name>No1</name>
<length>30</length>
</item >
XML解析
XML 的解析方式有2种
DOM:一次性将整个 XML 文档加载进内存,比较适合解析小的文件
SAX;从根元素开始,按书序开始,按顺序一个元素一个元素往下解析,比较适合解析大文件。
在iOS中,解析XML的手段有很多
苹果原生NSXMLParser:SAX方式解析,使用简单
-
三方框架:
- libxml2:纯C语言,默认包含在iOS SDK 中,同时支持DOM SAX方式解析
- GDataXML:DOM方式解析,由Google开发,基于libxml2
XML解析方式的选择
大文件:NSXMLParser、libxml2
小文件:GDataXML、NSXMLParser、libxml2
NSXMLParser
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
// 2.设置代理, 通过代理方法告诉NSXMLParser, 需要获取哪些元素和哪些属性
parser.delegate = self;
// 2.开始解析
[parser parse];
代理方法
-(void)parserDidStartDocument:(NSXMLParser *)parser{
NSLog(@"DidStartDocument");
}
// 只要解析完毕XML文档就会调用
-(void)parserDidEndDocument:(NSXMLParser *)parser{ NSLog(@"DidEndDocument");
// 刷新UI
[self.tableView reloadData];
}
// 只要开始解析一个元素就会调用
// elementName : 元素名称
// attributeDict : 元素中的属性
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
// NSLog(@"%@", elementName);
// NSLog(@"%@", attributeDict);
if ([elementName isEqualToString:@"items"])
{
return;
}
MitchellModel *model = [MitchellModel objectWithKeyValues:attributeDict];
[self.models addObject:video];
}
// 只要解析完一个元素就会调用
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
// NSLog(@"%@", elementName);
}
// 解析出现错误时调用
-(void)parser:(NSXMLParser *)parser validationErrorOccurred:(NSError *)validationError{
NSLog(@"error");
}
- GDataXMLDocument
// 1.创建解析器
GDataXMLDocument *document = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil];
// 2.获取根元素
GDataXMLElement *rootElement = document.rootElement;
// 3.从根元素中获取所有子元素
NSArray *elements = [rootElement elementsForName:@"item"];
// 4.遍历子元素, 取出属性转换为模型
for (GDataXMLElement *element in elements) {
MitchellModel *model = [[MitchellModel alloc] init];
model.ID = @([element attributeForName:@"id"].stringValue.integerValue);
model.image = [element attributeForName:@"image"].stringValue; model.url = [element attributeForName:@"url"].stringValue; model.name = [element attributeForName:@"name"].stringValue;
model.length = @([element attributeForName:@"length"].stringValue.integerValue);
[self. models addObject:video];
}
XML 增、删、改
上面已经了解XML语法、XML解析,现在我们来处理XML的数据库。
Demo的XML数据库先在工程里,对XML数据库进行操作后( 增、删、改)的到新的XML数据库,保存到沙盒里。
代码集成
- (void)change
{ //获取工程目录的xml文件
NSString *rootPath =[[NSString alloc]initWithString:[[NSBundle mainBundle]pathForResource:@"root"ofType:@"xml"]];
NSData *data1 = [[NSData alloc]initWithContentsOfFile:rootPath];
//使用NSData对象初始化
GDataXMLDocument *doc1 = [[GDataXMLDocument alloc] initWithData:data1 options:0 error:nil];
GDataXMLElement *ele1 = doc1.rootElement;
NSLog(@"%@---ele1",ele1);
//获取根节点(Navigation)
GDataXMLNode *node = [[ele1 elementsForName:@"Navigation"] objectAtIndex:0];
/** 删除节点 Navigation*/
[ele1 removeChild:node];
// NSString *path2 =[[NSString alloc]initWithString:[[NSBundle mainBundle]pathForResource:@"bbb"ofType:@"xml"]];
// NSData *data2 = [[NSData alloc]initWithContentsOfFile:path2];
//使用NSData对象初始化
GDataXMLDocument *doc2 = [[GDataXMLDocument alloc] initWithData:data1 options:0 error:nil];
GDataXMLElement *ele2 = doc2.rootElement;
//获取根节点(Navigation)
NSArray *array1 = [ele2 elementsForName:@"Navigation"];
NSLog(@"%@---array1",array1);for(GDataXMLElement *e in array1)
{
//获取根节点下的节点(Site)
NSArray *user = [e elementsForName:@"Site"];
for(int i=0;i<user.count;i++)
{
//取属性Name的值
GDataXMLElement *nameEle = [user objectAtIndex:i];
GDataXMLNode *node = [nameEle attributeForName:@"Name"];
//修改属性节点的值
[node setStringValue:[NSString stringWithFormat:@"张三%d",i]];
/** 属性Name值*/
NSString *str =[node stringValue];
NSLog(@"%@---",str);
}
}
NSLog(@"%@---array1",array1);
//给 ele1 添加一个节点,并设置当前节点的值
[ele1 addChild:array1[0]];
//获取路径对象
NSString *xmlPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//获取完整路径
NSString *plistPath1 = [xmlPath stringByAppendingPathComponent:@"aaa.xml"]; /** 写入道沙盒保存*/
NSMutableData *mutableData = [NSMutableData data];
GDataXMLDocument *doc4 = [[GDataXMLDocument alloc] initWithRootElement:ele1];
NSData *data2 = [doc4 XMLData];
[mutableData appendData:data2];
//写到沙盒
[mutableData writeToFile:plistPath1 atomically:YES];
}
- 最终沙盒的得到一份新的XML数据库,虽然属性‘Name’值不是NSString,但按照XML数据解析结果没问题的( #还望大神赐教)
<Site No="0" Name="客厅"/>
<Site No="1" Name="卧式A"/>
<Site No="2" Name="aa"/>
<Site No="3" Name="卧室c"/>
<Site No="4" Name="影音室"/>
<Site No="5" Name="健身房"/>