気楽なソフト工房

プログラミングについていろいろな記事を書いています。



mykonos2008

Author:mykonos2008
システムエンジニアとして働いている30代の会社員です。
仕事や趣味でプログラムを書いている方の役に立つ記事を書いていきたいと思っています。
ご意見、ご感想はこちらまで
If you are an english speaker,Please visit my english blog.

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
今回は「ChimeraXML」で配列型の要素を解析する方法を解説します。

以下のようなXMLがあります。

<goods>
    <goods-name>iPhone5S</goods-name>
    <categories>
        <category>
            <category-code>001</category-code>
            <category-name>telephone</category-name>
        </category>
        <category>
            <category-code>002</category-code>
            <category-name>music player</category-name>
        </category>
    </categories>
</goods>

[categories]要素は子要素として複数の[category]要素を持っています。
このような形式のXMLをデシリアライズする場合、[ChimeraXML]ではNSArray型のプロパティを使用します。

まず、先にNSArray型のプロパティに格納する[category]に対応するエンティティを定義します。

[CategoryEntity.h]
#import "CPXmlEntity.h"

@interface CategoryEntity : CPXmlEntity

@property(strong,nonatomic) NSString *categoryCode;
@property(strong,nonatomic) NSString *categoryName;

@end

[CategoryEntity.m]
#import "CategoryEntity.h"

@implementation CategoryEntity

+ (id)propertyInfoForElement:(NSString *)element
{
    static NSDictionary *propDic;
    
    if(!propDic){
        
        propDic = @{
                    @"category-code": @"categoryCode",
                    @"category-name": @"categoryName"
                    };
    }
    
    return propDic[element];
}

@end

[goods]要素に対応するGoodsEntityにはNSArray型のcategoriesプロパティを定義します。

[GoodsEntity.h]
#import "CPXmlEntity.h"

@interface GoodsEntity : CPXmlEntity

@property(strong,nonatomic) NSString *goodsName;
@property(strong,nonatomic) NSArray *categories;

@end

実装ファイルでは、categoriesプロパティの詳細情報を[propertyInfoForElement:]の戻り値として
解析エンジンに提供する必要があります。

[GoodsEntity.m]
#import "GoodsEntity.h"
#import "CategoryEntity.h"

@implementation GoodsEntity

+ (id)propertyInfoForElement:(NSString *)element
{
    static NSDictionary *propDic;
    
    if(!propDic){
        
        CPPropertyInfo *categories = [[CPPropertyInfo alloc] init];
        categories.name = @"categories";
        categories.childType = [CategoryEntity class];
        
        propDic = @{
                    @"goods-name": @"goodsName",
                    @"categories": categories
                    };
    }
    
    return propDic[element];
}

@end

[category]要素に対応するプロパティのメタ情報として、CPPropertyInfo型のオブジェクトを返却します。
CPPropertyInfoのnameプロパティには、プロパティ名を設定します。
そして、childTypeに、NSArrayに格納するオブジェクトの型を指定します。ここでは、CategoryEntity型を指定しています。

Objective-CにはJavaのようにジェネリックコレクションの仕組が無いため、childTypeにより、
解析エンジンに子要素の型情報を提供しているのです。

childTypeにはサンプルのようにCPXmlEntityクラスを継承するクラスの他、
NSStringとNSNumber型を指定することが出来ます。

その場合、解析対象のXMLは以下のような形になります。

<goods>
    <goods-name>iPhone5S</goods-name>
    <categories>
        <category-code>001</category-code>
        <category-code>002</category-code>
    </categories>
</goods>

解析を実行する処理はこれまでの例と同じです。

    NSData *data = [xmlText dataUsingEncoding:NSUTF8StringEncoding];
    ChimeraParser *chimeraParser = [[ChimeraParser alloc] initWithTargetClass:[GoodsEntity class]];
    GoodsEntity *goods = [chimeraParser parse:data];
    
    NSLog(@"goodsName = %@",goods.goodsName);
    for(id category in goods.categories) {
        NSLog(@"categoryCode = %@",[category categoryCode]);
        NSLog(@"categoryName = %@",[category categoryName]);
    }

NSArray型のプロパティには、実際にはNSMutableArray型のオブジェクトが設定されます。

暗黙的な配列の解析



以下のXMLを見てください。[goods]要素の子要素として、[category]要素が
複数回出現します。上記のサンプルとの違いは、[category]要素の上に
[categories]要素が存在しているかどうかです。

<goods>
    <goods-name>iPhone5S</goods-name>
    <category>
        <category-code>001</category-code>
        <category-name>telephone</category-name>
    </category>
    <category>
        <category-code>002</category-code>
        <category-name>music player</category-name>
    </category>
</goods>

上記のように、暗黙的な配列型要素を解析する場合、コードを少し変更する必要があります。

[GoodsEntity]の[propertyInfoForElement:]メソッドを以下のように変更します。

+ (id)propertyInfoForElement:(NSString *)element
{
    static NSDictionary *propDic;
    
    if(!propDic){
        
        CPPropertyInfo *categories = [[CPPropertyInfo alloc] init];
        categories.name = @"categories";
        categories.childType = [CategoryEntity class];
        categories.implicitArray = YES; //この行を追加
        
        propDic = @{
                    @"goods-name": @"goodsName",
                    //@"categories": categories
                    @"category": categories //対応する要素名を変更
                    };
    }
    
    return propDic[element];
}

CPPropertyInfoのimplicitArrayにYESを設定します。
また、要素名が[category]に対して、配列型のプロパティが対応するように変更しています。


コメント

コメントの投稿

管理者にだけ表示を許可する

トラックバック

http://csfun.blog49.fc2.com/tb.php/129-376c9696

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。