1、XML解析html
對於JSON解析,iOS5以前有比較多的開源三方類(如JSONKit等)支持,一行代碼搞定;iOS5後JSON能夠用原生API解析,不只方便並且高效。可是XML解析原生的API不是很友好,解析也麻煩;還好能夠用Google的GDataXML來解析,怎麼集成GDataXML到工程請查看我之前的隨筆,用GDataXML稍稍好解析一點,XML的解析原理能夠理解成:脫衣模式,想要洗澡就要把衣服從外到裏依次脫掉,而後每件衣服均可以看作是一個GDataElement,每個GDataElement都有本身的值與屬性,下面來解析如下XML數據。node
XML文件數據(文件名位Attribute.xml):數組
<list> <OrderData xmlns:name_space="http://www.baidu.com" xmlns="http://www.google.com/hk" attribute="party's attribute" 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來打印):google
+ (void)parseXMLDemo { NSError *error = nil; NSString *filePath0 = [[NSBundle mainBundle] pathForResource:@"Attribute" ofType:@"xml"]; NSData *xmldata0 = [[NSData alloc] initWithContentsOfFile:filePath0]; GDataXMLDocument *doc0 = [[GDataXMLDocument alloc] initWithData:xmldata0 options:0 error:&error]; GDataXMLElement *rootElement = doc0.rootElement; if(error != nil) { NSLog(@"Attribute.xml parsed error!\n%@", [error localizedDescription]); return; } NSLog(@"%@", rootElement); NSArray *messages = [rootElement elementsForName:@"OrderData"]; if (messages.count > 0) { for (GDataXMLElement *element in messages) { //取OrderData的HASH屬性值 NSLog(@"attrute:%@", [[element attributeForName:@"HASH"] stringValue]); //獲取全部命名空間nameSpaces NSArray *nameSpaces = [element namespaces];// if (nameSpaces.count > 0) { [nameSpaces enumerateObjectsUsingBlock:^(GDataXMLNode *node, NSUInteger idx, BOOL *stop) { //獲取全部命名空間的名字與值 NSLog(@"|%@:%@|", [node name], [node 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;atom
能夠經過路徑直接獲取相應的節點:NSArray *nodes = [doc nodesForXPath:@"//Party/Player" error:&error];,這樣作得好處是在一個比較複雜的XML文件中不用一層一層的遍歷,直接取到直接想要的那層。spa
2、XML建立code
XML建立與解析是一個逆過程,能夠理解爲:穿衣模式,冬天起牀,創衣服的順序依次是穿裏衣,毛衣,外套等。建立XML文件也是同樣,先建立添加最裏層元素(GDataXMLElement),那麼下面咱們來建立有如下數據的xml文件orm
<Party xmlns:name space="http://www.baidu.com" xmlns="http://www.google.com/hk" attribute="party's attribute"> <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類xml
// 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這裏沒有給出,請讀者直接寫一下哈)htm
+ (void)saveParty:(Party *)aParty { GDataXMLElement *partyElement = [GDataXMLElement elementWithName:@"Party"]; //添加屬性 [partyElement addAttribute:[GDataXMLNode elementWithName:@"attribute" stringValue:@"party's attribute"]]; //添加命名空間 [partyElement addNamespace:[GDataXMLNode namespaceWithName:@"name space" stringValue:@"http://www.baidu.com"]]; //添加缺省命名空間 [partyElement addNamespace:[GDataXMLNode namespaceWithName:@"" stringValue:@"http://www.google.com/hk"]]; for (Player *player in aParty.players) { GDataXMLElement *playerElement = [GDataXMLNode elementWithName:@"Player"]; // 建立元素 GDataXMLElement *nameElement = [GDataXMLNode elementWithName:@"Name" stringValue:player.name]; GDataXMLElement *levelElement = [GDataXMLNode 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 = [GDataXMLNode 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建立也不難吧(若有不合理地方請指正,謝謝!)