XML解析与创建(GDataXML)

 一、XML解析

  对于JSON解析,iOS5之前有比较多的开源三方类(如JSONKit等)支持,一行代码搞定;iOS5后JSON可以用原生API解析,不仅方便而且高效。但是XML解析原生的API不是很友好,解析也麻烦;还好可以用Google的GDataXML来解析,怎么集成GDataXML到工程请查看我以前的随笔,用GDataXML稍稍好解析一点,XML的解析原理可以理解成:脱衣模式,想要洗澡就要把衣服从外到里依次脱掉,然后每件衣服都可以看做是一个GDataElement,每一个GDataElement都有自己的值与属性,下面来解析以下XML数据。

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来打印):

+ (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;

可以通过路径直接获取相应的节点:NSArray *nodes = [doc nodesForXPath:@"//Party/Player" error:&error];,这样做得好处是在一个比较复杂的XML文件中不用一层一层的遍历,直接取到直接想要的那层。

 

二、XML创建

XML创建与解析是一个逆过程,可以理解为:穿衣模式,冬天起床,创衣服的顺序依次是穿里衣,毛衣,外套等。创建XML文件也是一样,先创建添加最里层元素(GDataXMLElement),那么下面我们来创建有以下数据的xml文件

<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类

//  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:[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创建也不难吧(如有不合理地方请指正,谢谢!)

你可能感兴趣的:(xml解析)