一、XML 可扩展标记语言
是什么?是一段有规范的字符串,
用在哪?用在任何地方
语法:
* 结点Node
<结点名 属性名="属性值">
结点内容
</结点名>
* 结点的开始和结尾配对
* 结点内可以有子结点
* 结点内可以有文本
* 结点名和属性名区分大小写
* 结点不能交叉
* 结点名和属性名 随便写
术语:
结点、属性
叶子结点 :没有子结点的结点
<a b="c"></a>可以简化<a b="c" />
非叶子结点 :有子结点的结点
对于存储数据的xml,非叶子结点几乎不存储任何文本,对于一些xml的变体xhtml,就会出现大量的非叶子子结点存储文本的现象,比如:
<div>
<h1>...</h1>
<p>ggg...<a>...</a></p>
</div>
根结点 :没有父结点的结点,一个xml只能有一个根结点
层级关系:
子结点
父结点
兄弟结点
其他:特殊符号不能直接写在xml中,比如<要写成< >>
xml解析:
XML文件结构解析
1 事件驱动 SAX iOS采用事件驱动解析
ios具体解析xml文档步骤:
1) 准备好xml文档的路径
2) 转换为data数据
3) 创建NSXMLParser对象调用initWithData把data传进来
4) 设置delegate,然后发送parse消息解析文档
NSString *path = @"/.../message.xml";
NSData *data = [NSData dataWithContentsOfFile:path];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:data];
xmlParser.delegate = self;
[xmlParser parse];
delegate中几个重要的API:
// 开始解析xml文档 -(void)parserDidStartDocument:(NSXMLParser *)parser{ NSLog(@"开始解析..."); } // 发现结点 节点名 + 属性 -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{ NSLog(@"开始节点名:%@",elementName); [attributeDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { NSLog(@"属性名:%@, 属性值:%@",key,obj); }]; } // 结束结点 -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{ NSLog(@"结束结点:%@",elementName); } // 发现文本 -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ NSLog(@"发现文本:%@",string); } // 结束解析xml文档 -(void)parserDidEndDocument:(NSXMLParser *)parser{ NSLog(@"结束文档解析"); }
实现xml解析步骤:
/*
解析xml文档:
根据本例中message.xml文件解析
如果发现Message节点就创建一个类,同时根据attributeDict可以获取到属性order并赋值
为了可以获取xml文件中文本的值并赋给message类的属性(节点名),需要记下最近的那个节点名lastElementName
在发现文本方法中判断lastElementName是否和message类中的属性相同,如果相同就赋值
注意:文本直接赋值会出问题,"\n"这个会覆盖赋值好的文本,所以在结束结点中应该给lastElementName置空
快速修改本文件中所有的属性名技巧:
选中属性名后右击选中refactor -> rename
*/
#import "MXMessageParse.h" #import "MXMessage.h" @interface MXMessageParse () @property(nonatomic,strong) MXMessage *lastMessage; @property(nonatomic,copy) NSString *lastElementName; @property(nonatomic,strong) NSMutableArray *messages; @end @implementation MXMessageParse -(void)parser{ NSString *path = @"/Users/tarena/yz/第三阶段(UI核心_Model赵哲)/day03/day0302_xml_parse解析/message.xml"; NSData *data = [NSData dataWithContentsOfFile:path]; NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:data]; xmlParser.delegate = self; [xmlParser parse]; } // 开始解析xml文档 -(void)parserDidStartDocument:(NSXMLParser *)parser{ NSLog(@"开始解析..."); } // 发现结点 节点名 + 属性 -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{ NSLog(@"开始节点名:%@",elementName); [attributeDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { NSLog(@"属性名:%@, 属性值:%@",key,obj); }]; if ([elementName isEqualToString:@"Message"]) { self.lastMessage = [[MXMessage alloc] init]; self.lastMessage.order = [attributeDict[@"order"] intValue]; }else if ([elementName isEqualToString:@"messages"]){ self.messages = [NSMutableArray array]; } self.lastElementName = elementName; } // 结束结点 -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{ NSLog(@"结束结点:%@",elementName); if ([elementName isEqualToString:@"Message"]) { [self.messages addObject:self.lastMessage]; } self.lastElementName = Nil; } // 发现文本 -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ NSLog(@"发现文本:%@",string); if ([self.lastElementName isEqualToString:@"fromMe"]) { self.lastMessage.fromMe = [string isEqualToString:@"YES"]; }else if ([self.lastElementName isEqualToString:@"type"]){ NSString *type = string; if ([type isEqualToString:@"TXT"]) { self.lastMessage.type = MXMessageTypeText; } }else if ([self.lastElementName isEqualToString:@"content"]){ self.lastMessage.content = string; } } // 结束解析xml文档 -(void)parserDidEndDocument:(NSXMLParser *)parser{ NSLog(@"结束文档解析"); }
2 树状模型 DOM
XML结构 <-> 对象
Node *rootNode = [parser parse:path];
NSString *elementName = rootNode.name;
Node *messageNode = [rootNode childNodeOfName@"Message"];
messageNode.name;
[messageNode attributeByName:@"order"];
3 优缺点对比
事件驱动 树状模型
使用困难 使用简单
边读取边解析 读取完整后在解析
摘取部分重要信息 从完整信息中搜索
二、plist (Property List)
是一个有固定格式的xml文件,用来存储中小型数据,在ios中使用
plist可以存储的数据类型:
NSArray
NSDictionary
根节点必须是上面两个类型之一
NSString
NSNumber
NSData
Boollean
plist解析:
NSArray arrayWithContentsOfFile
NSDictionary dictionaryWithContentsOfFile
plist的解析过程是
plist(XML) <--> OC对象结构 互相转换
对应关系:
OC
<Message order="">
+ fromMe
+ content
MXL
Message
<formMe></formMe>
<content></content>
Plist
formMe ->
content ->
读取plist中的数据
- (void)viewDidLoad { [super viewDidLoad]; // 读取plist数据 NSMutableArray *arr = [NSMutableArray array]; NSString *path = [[NSBundle mainBundle] pathForResource:@"messages" ofType:@"plist"]; NSArray *array = [NSArray arrayWithContentsOfFile:path]; for (NSDictionary *dic in array) { MXMessage *message = [[MXMessage alloc] init]; message.content = dic[@"content"]; message.fromMe = [dic[@"fromMe"] boolValue]; if ([dic[@"type"] isEqualToString:@"TXT"]) { message.type = MXMessageTypeText; } [arr addObject:message]; } for (MXMessage *message in arr) { NSLog(@"%@",message.content); } }
写入:
writeToFile:
必须确保字典/数组内的所有对象均是plist支持的对象
复杂对象树状结构用plist表达
area
代码如下:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSLog(@"%@",NSHomeDirectory()); NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"china.plist"]; [[NSFileManager defaultManager] createFileAtPath:plistPath contents:Nil attributes:Nil]; // 对象 -> 字典 TRArea * puDong = [[TRArea alloc] init]; puDong.areaName = @"浦东"; NSDictionary *dicPuDong = @{@"areaName": puDong.areaName}; TRArea * shangHai = [[TRArea alloc] init]; shangHai.areaName = @"上海"; shangHai.subAreas = @[dicPuDong]; NSDictionary *dicShangHai = @{@"areaName": shangHai.areaName, @"subAreas": shangHai.subAreas}; TRArea * china = [[TRArea alloc] init]; china.areaName = @"中国"; china.subAreas = @[dicShangHai]; NSDictionary *dicChina = @{@"areaName": china.areaName, @"subAreas": china.subAreas}; [dicChina writeToFile:plistPath atomically:YES]; }
03-IOSCore - XML及解析、Plist,布布扣,bubuko.com
原文:http://www.cnblogs.com/yangmx/p/3583094.html