気楽なソフト工房

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



mykonos2008

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

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
このドキュメントはObjective-C用のXMLデシリアライズライブラリ「ChimeraXML」のチュートリアルです。

シンプルなXMLの解析


以下のようなシンプルなXMLをChimeraXMLで解析してみます。

<person>
    <first-name>Taro</first-name>
    <last-name>Yamada</last-name>
    <age>22</age>
</person>

ChimeraXMLでXMLを解析する手順の大半は、デシリアライズ先となるオブジェクトのクラスを定義することです。
解析そのものは数行のコードで実行可能です。

デシリアライズ先となるオブジェクトのクラスはCPXmlEntityクラスを継承し、解析対象のXMLの要素に対応する
プロパティを持つクラスになります。クラス名にルールは有りません。

プロパティ名はXMLの要素名と一致させる必要はありません。プロパティ名と要素名のマッピング情報は、CPXmlEntityクラスの
クラスメソッド「propertyInfoForElement:」により、ChimeraXMLの解析エンジンに提供します。

CPXmlEntityを継承する各クラスは、propertyInfoForElement:」をオーバーライドする必要があります。

まず、上記サンプルXMLのデシリアライズとなるクラスのヘッダファイルを見てみましょう。

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

@interface PersonEntity : CPXmlEntity

@property(strong,nonatomic) NSString *firstName;
@property(strong,nonatomic) NSString *lastName;
@property(strong,nonatomic) NSNumber *age;

@end

XMLの要素、fist-name、last-name、ageに対応するプロパティfirstName、lastName、ageを定義しています。プロパティ名を
要素名に一致させる必要はありません。

ChimeraXMLで扱うことが出来るプロパティの型は、NSString、NSNumber、CPXmlEntityクラスを継承するクラス、NSArrayの4つです。
CPXmlEntityクラスを継承するクラス、NSArrayをプロパティとして使用する方法は後述します。

XMLが持つ全ての要素について、プロパティを定義する必要はありません。アプリケーションで必要な項目のみを
プロパティとして定義しておけば問題ありません。

次に実装クラスです。

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

@implementation PersonEntity

+ (id)propertyInfoForElement:(NSString *)element
{
    if([element isEqualToString:@"first-name"]) {
        return @"firstName";
    }
    else if([element isEqualToString:@"last-name"]) {
        return @"lastName";
    }
    else if([element isEqualToString:@"age"]) {
        return @"age";
    }
    
    return nil;
}

@end

CPXmlEntityの[propertyInfoForElement:]をオーバーライドし、XMLの要素に対応するプロパティの名前を返却しています。
戻り値がid型になっているのは、NSString型以外を返す必要があるケースがあるからです。(これについては後述します。)

XMLが持つ全ての要素、クラスが持つ全てのプロパティについて、このメソッドの戻り値を提供する必要はありません。
このメソッドが戻り値を提供しない(nilを返す)要素については、解析エンジンが無視をします。

上記のようにif文で要素名に応じて分岐を記述する方法でも問題ないですが、以下のようにNSDictionaryを使用することで
簡潔に記述することが可能です。

+ (id)propertyInfoForElement:(NSString *)element
{    
    static NSDictionary *propDic;
    
    if(!propDic){
        
        propDic = @{
                    @"first-name": @"firstName",
                    @"last-name": @"lastName",
                    @"age": @"age"
                    };
    }
    
    return propDic[element];
}

次に解析を実行する部分です。

NSData *data = [xmlText dataUsingEncoding:NSUTF8StringEncoding]; //xmlTextは解析対象のXMLを管理するNSString型変数
ChimeraParser *chimeraParser = [[ChimeraParser alloc] initWithTargetClass:[PersonEntity class]];
PersonEntity *person = [chimeraParser parse:data];

解析を実行するのはChimeraParserクラスです。「initWithTargetClass:」にデシリアライズ先のオブジェクトのクラスを指定して初期化します。
解析はparseメソッドにより行われます。戻り値として、initWithTargetClassに指定したクラスのオブジェクトが返却されます。
返されたオブジェクトのプロパティには、対応するXMLの要素の値が設定されています。

NSNumber型のプロパティに対応する要素に文字列以外の値が設定されている場合、プロパティには値が設定されません。


コメント

コメントの投稿

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

トラックバック

http://csfun.blog49.fc2.com/tb.php/127-f56b2cc8

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