一、XML解析
对于JSON解析,iOS5之前有比较多的开源三方类(如JSONKit等)支持,一行代码搞定;iOS5后JSON可以用原生API解析,不仅方便而且高效。但是XML解析原生的API不是很友好,解析也麻烦;还好可以用Google的GDataXML来解析,怎么集成GDataXML到工程请查看我以前的随笔,用GDataXML稍稍好解析一点,XML的解析原理可以理解成:脱衣模式,想要洗澡就要把衣服从外到里依次脱掉,然后每件衣服都可以看做是一个GDataElement,每一个GDataElement都有自己的值与属性,下面来解析以下XML数据。
XML文件数据(文件名位Attribute.xml):
<list>
<OrderData HASH="1408108039">od0</OrderData>
<OrderData HASH="208524692">
<id>97</id>
<customer>
<CustomerData HASH="2128670187">cd</CustomerData>
</customer>
<billingAddress>ba</billingAddress>
<deliveryAddress>da</deliveryAddress>
<orderDetail>
<list>
<OrderDetailData HASH="516790072">odd10</OrderDetailData>
<OrderDetailData HASH="11226247">odd11</OrderDetailData>
<OrderDetailData HASH="11226247">odd12</OrderDetailData>
</list>
</orderDetail>
<log>l</log>
</OrderData>
<OrderData HASH="1502226778">odd20</OrderData>
</list>
OC解析代码(所有element的值与属性用log来打印):
NSError *error = nil;
NSString *filePath0 = [[NSBundle mainBundle] pathForResource:@"Attribute" ofType:@"xml"];// 获取工程内Attribute.xml文件
NSData *xmldata0 = [[NSData alloc] initWithContentsOfFile:filePath0];
GDataXMLDocument *doc0 = [[GDataXMLDocument alloc] initWithData:xmldata0 options:0 error:&error];
GDataXMLElement *rootElement = doc0.rootElement;//获取跟节点
NSLog(@"%@", rootElement);
NSArray *messages = [rootElement elementsForName:@"OrderData"];
if (messages.count > 0) {
for (GDataXMLElement *element in messages) {
//取OrderData的HASH属性值
NSLog(@"attrute:%@", [[element attributeForName:@"HASH"] stringValue]);
//取OrderData的HASH属性值,如果没有值,取出来的则是所有子值的组合(这里是:97cdbadaodd10odd11odd12l)
NSLog(@"OrderData:%@", [element stringValue]);
//获取id子元素数组
NSArray *elementIDs = [element elementsForName:@"id"];
if (elementIDs.count > 0) {
for (GDataXMLElement *eID in elementIDs) {
NSLog(@"id:%d", [[eID stringValue] intValue]); // 获取ID的值
}
}
//获取customer子元素数组
NSArray *elementCustomers = [element elementsForName:@"customer"];
if (elementCustomers.count > 0) {
for (GDataXMLElement *eID in elementCustomers) {
NSArray *customerDatas = [eID elementsForName:@"CustomerData"];
if (customerDatas.count > 0) {
for (GDataXMLElement *customerData in customerDatas) {
NSLog(@"customerData:%@", [customerData stringValue]); // 获取customerData的值
NSLog(@"customerData-attrute:%@", [[customerData attributeForName:@"HASH"] stringValue]); // 获取customerData的HASH属性值
}
}
}
}
//获取billingAddress子元素数组
NSArray *elementBillingAddresses = [element elementsForName:@"billingAddress"];
if (elementBillingAddresses.count > 0) {
for (GDataXMLElement *eID in elementBillingAddresses) {
NSLog(@"billingAddress:%@", [eID stringValue]); // 获取billingAddress的值
}
}
//获取deliveryAddress子元素数组
NSArray *elementDeliveryAddressses = [element elementsForName:@"deliveryAddress"];
if (elementDeliveryAddressses.count > 0) {
for (GDataXMLElement *eID in elementDeliveryAddressses) {
NSLog(@"deliveryAddress:%@", [eID stringValue]);// 获取deliveryAddress的值
}
}
//获取orderDetail子元素数组
NSArray *elementOrderDetails = [element elementsForName:@"orderDetail"];
if (elementOrderDetails.count > 0) {
for (GDataXMLElement *eID in elementOrderDetails) {
NSArray *lists = [eID elementsForName:@"list"];
if (lists.count > 0) {
for (GDataXMLElement *list in lists) {
NSArray *OrderDetailDatas = [list elementsForName:@"OrderDetailData"];
if (OrderDetailDatas.count > 0) {
for (GDataXMLElement *OrderDetailData in OrderDetailDatas) {
NSLog(@"OrderDetailData-attribute:%@", [[OrderDetailData attributeForName:@"HASH"] stringValue]);
NSLog(@"OrderDetailData:%@", [OrderDetailData stringValue]);
}
}
}
}
}
}
//获取log子元素数组
NSArray *elementLogs = [element elementsForName:@"log"];
if (elementLogs.count > 0) {
for (GDataXMLElement *eID in elementLogs) {
NSLog(@"log:%@", [eID stringValue]);// 获取log的值
}
}
}
}
这样一层一层的解析是不是很清楚,妈妈在也不用担心我解不了复杂的XML了。在这里分享一个小技巧,获取节点的时候不用这样获取节点:GDataXMLElement *rootElement = doc.rootElement;
可以通过路径直接获取相应的节点:NSArray *nodes = [doc nodesForXPath:@"//Party/Player" error:&error];,这样做得好处是在一个比较复杂的XML文件中不用一层一层的遍历,直接取到直接想要的那层。
二、XML创建
XML创建与解析是一个逆过程,可以理解为:穿衣模式,冬天起床,创衣服的顺序依次是穿里衣,毛衣,外套等。创建XML文件也是一样,先创建添加最里层元素(GDataXMLElement),那么下面我们来创建有以下数据的xml文件
<Party>
<Player>
<Name>Butch</Name>
<Level>1</Level>
<Class>Fighter</Class>
</Player>
<Player>
<Name>Shadow</Name>
<Level>2</Level>
<Class>Rogue</Class>
</Player>
<Player>
<Name>Crak</Name>
<Level>3</Level>
<Class>Wizard</Class>
</Player>
</Party>
为了在简化创建的代码与逻辑,我们先创建Player与Party两个OC类
// Player.h文件
#import <Foundation/Foundation.h>
typedef enum {
RPGClassFighter = 0,
RPGClassRogue,
RPGClassWizard
} RPGClass;
@interface Player : NSObject
@property (copy, nonatomic) NSString *name;
@property int level;
@property RPGClass rpgClass;
- (id)initWithName:(NSString *)aName level:(int)aLevel rpgClass:(RPGClass)aRPGClass;
@end
// Player.m文件
#import "Player.h"
@implementation Player
- (id)initWithName:(NSString *)aName level:(int)aLevel rpgClass:(RPGClass)aRPGClass {
if (self = [super init]) {
_name = aName;
_level = aLevel;
_rpgClass = aRPGClass;
}
return self;
}
@end
// Party.h文件
#import <Foundation/Foundation.h>
@interface Party : NSObject
@property (strong, nonatomic) NSMutableArray *players;
@end
// Party.m
#import "Party.h"
#import "Player.h"
@implementation Party
- (instancetype)init
{
self = [super init];
if (self) {
_players = [[NSMutableArray alloc] init];
}
return self;
}
@end
创建XML方法(创建三个Player这里没有给出,请读者直接写一下哈)
+ (void)saveParty:(Party *)aParty {
GDataXMLElement *partyElement = [GDataXMLElement elementWithName:@"Party"];
[partyElement addAttribute:[GDataXMLElement elementWithName:@"attribute" stringValue:@"party‘s attribute"]];
for (Player *player in aParty.players) {
GDataXMLElement *playerElement = [GDataXMLElement elementWithName:@"Player"]; // 创建元素
GDataXMLElement *nameElement = [GDataXMLElement elementWithName:@"Name" stringValue:player.name];
GDataXMLElement *levelElement = [GDataXMLElement elementWithName:@"Level" stringValue:[NSString stringWithFormat:@"%d", player.level]];
NSString *rpgClass = nil;
if (player.rpgClass == RPGClassFighter) {
rpgClass = @"Fighter";
} else if (player.rpgClass == RPGClassRogue) {
rpgClass = @"Rogue";
}else if (player.rpgClass == RPGClassWizard) {
rpgClass = @"Wizard";
}
GDataXMLElement *rpgClassElement = [GDataXMLElement elementWithName:@"Class" stringValue:rpgClass];
[playerElement addChild:nameElement]; // 给player添加name元素
[playerElement addChild:levelElement]; // 给player添加level元素
[playerElement addChild:rpgClassElement]; // 给player添加rpgClass元素
[partyElement addChild:playerElement]; // 给party添加player元素
}
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithRootElement:partyElement];
NSData *xmlData = [doc XMLData];
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"makeXMLFile.xml"];
[xmlData writeToFile:filePath atomically:YES];
}
看完代码是不是觉得XML创建也不难吧(如有不合理地方请指正,谢谢!)
原文:http://www.cnblogs.com/ericiOScnblogs/p/4207984.html