XML解析與建立(GDataXML)

 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建立也不難吧(若有不合理地方請指正,謝謝!)

相關文章
相關標籤/搜索