首页 > 其他 > 详细

03-IOSCore - XML及解析、Plist

时间:2014-03-05 21:20:55      阅读:544      评论:0      收藏:0      [点我收藏+]

一、XML 可扩展标记语言

是什么?是一段有规范的字符串,

用在哪?用在任何地方

 

语法:

* 结点Node

<结点名 属性名="属性值">

         结点内容

</结点名>

* 结点的开始和结尾配对

* 结点内可以有子结点

* 结点内可以有文本

* 结点名和属性名区分大小写

* 结点不能交叉

* 结点名和属性名 随便写

 

术语:

结点、属性

叶子结点  :没有子结点的结点

         <a b="c"></a>可以简化<a b="c" />

非叶子结点  :有子结点的结点

         对于存储数据的xml,非叶子结点几乎不存储任何文本,对于一些xml的变体xhtml,就会出现大量的非叶子子结点存储文本的现象,比如:

         <div>

                 <h1>...</h1>

                 <p>ggg...<a>...</a></p>

         </div>

根结点  :没有父结点的结点,一个xml只能有一个根结点

层级关系:

子结点

父结点

兄弟结点

其他:特殊符号不能直接写在xml中,比如<要写成&lt;    >&gt;

 

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:

bubuko.com,布布扣
// 开始解析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(@"结束文档解析");

}
bubuko.com,布布扣

 

实现xml解析步骤:

/*

 解析xml文档:

 根据本例中message.xml文件解析

 如果发现Message节点就创建一个类,同时根据attributeDict可以获取到属性order并赋值

 为了可以获取xml文件中文本的值并赋给message类的属性(节点名),需要记下最近的那个节点名lastElementName

 在发现文本方法中判断lastElementName是否和message类中的属性相同,如果相同就赋值

 注意:文本直接赋值会出问题,"\n"这个会覆盖赋值好的文本,所以在结束结点中应该给lastElementName置空

 

 快速修改本文件中所有的属性名技巧:

 选中属性名后右击选中refactor -> rename

 */

bubuko.com,布布扣
#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(@"结束文档解析");

}
View Code

 

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中的数据

bubuko.com,布布扣
- (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);

    }

}
bubuko.com,布布扣

 

写入:

writeToFile:

必须确保字典/数组内的所有对象均是plist支持的对象

 

复杂对象树状结构用plist表达

                 area

代码如下:

bubuko.com,布布扣
- (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];

}
View Code

 

 

03-IOSCore - XML及解析、Plist,布布扣,bubuko.com

03-IOSCore - XML及解析、Plist

原文:http://www.cnblogs.com/yangmx/p/3583094.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!