データ バインド ウィザードによる XML ドキュメントの抽象化
TXMLDocument コンポーネントや XML ドキュメント内のノードにエクスポーズする IXMLNode インターフェースだけを使って XML ドキュメントを操作することは可能です。または,TXMLDocument さえ使用せずに DOM インターフェースだけを処理することもできます。しかし,より単純で読みやすいコードを記述するには,XML データバインドウィザードを使用するのがよいでしょう。
データバインドウィザードは,XML スキーマまたはデータファイルを受け取り,その上にマップされるインターフェースのセットを生成します。たとえば,次のような XML データがあるとします。
<customer id=1> <name>Mark</name> <phone>(831) 431-1000</phone> </customer>
データバインドウィザードは,次のインターフェース(およびこれを実装するクラス)を生成します。
ICustomer = interface(IXMLNode)
['{8CD6A6E8-24FC-426F-9718-455F0C507C8E}']
{ プロパティアクセッサ }
function Get_Id: Integer;
function Get_Name: WideString;
function Get_Phone: WideString;
procedure Set_Id(Value: Integer);
procedure Set_Name(Value: WideString);
procedure Set_Phone(Value: WideString);
{ メソッドとプロパティ }
property Id: Integer read Get_Id write Set_Id;
property Name: WideString read Get_Name write Set_Name;
property Phone: WideString read Get_Phone write Set_Phone;
end;
__interface INTERFACE_UUID("{F3729105-3DD0-1234-80e0-22A04FE7B451}") ICustomer :
public IXMLNode
{
public:
virtual int __fastcall Getid(void) = 0 ;
virtual DOMString __fastcall Getname(void) = 0 ;
virtual DOMString __fastcall Getphone(void) = 0 ;
virtual void __fastcall Setid(int Value)= 0 ;
virtual void __fastcall Setname(DOMString Value)= 0 ;
virtual void __fastcall Setphone(DOMString Value)= 0 ;
__property int id = {read=Getid, write=Setid};
__property DOMString name = {read=Getname, write=Setname};
__property DOMString phone = {read=Getphone, write=Setphone};
};
あらゆる子ノードは,ある条件を満たすプロパティにマップされます。その条件とは,プロパティの名前がその子ノードのタグ名に一致し,(子が内部ノードの場合は)プロパティの値がその子ノードのインターフェースであるか,(リーフノードの場合は)プロパティの値がその子ノードの値であることです。あらゆるノード属性もプロパティにマップされ,マップ先のプロパティは,名前が属性の名前と一致し,値が属性の値と一致するプロパティになります。
XML ドキュメント内のタグ付き要素のそれぞれに対してインターフェース(および実装クラス)を作成するほかに,データバインドウィザードは,ルートノードへのインターフェースを取得するグローバル関数を作成します。たとえば,上記の XML の出典であるドキュメントのルートノードにタグ <Customers> がある場合,データバインドウィザードは次のグローバルルーチンを作成します。
function Getcustomers(Doc: IXMLDocument): IXMLCustomerType;
function Loadcustomers(const FileName: WideString): IXMLCustomerType;
function Newcustomers: IXMLCustomerType;
extern PACKAGE _di_ICustomers __fastcall GetCustomers(TXMLDocument *XMLDoc);
extern PACKAGE _di_ICustomers __fastcall GetCustomers(_di_IXMLDocument XMLDoc);
extern PACKAGE _di_ICustomers __fastcall LoadCustomers(const WideString FileName);
extern PACKAGE _di_ICustomers __fastcall NewCustomers(void);
Get... 関数は,TXMLDocument インスタンスのインターフェースラッパーを取得します。Load... 関数は,TXMLDocument インスタンスを動的に作成し,インターフェースポインタを返す前に,指定された XML ファイルを値としてロードします。New... 関数は,新しい(空の)TXMLDocument インスタンスを作成し,ルートノードへのインターフェースを返します。
生成されたインターフェースは XML ドキュメントの構造をより直接的に反映しているので,このインターフェースを使用するとコードを単純にできます。たとえば,このインターフェースを使用せずに記述したコードは次のようになります。
CustIntf := XMLDocument1.DocumentElement;
CustName := CustIntf.ChildNodes[0].ChildNodes['name'].Value;
_di_IXMLNode CustIntf = XMLDocument1->DocumentElement;
CustName = CustIntf->ChildNodes->Nodes->GetNode(0)->ChildNodes->Nodes[WideString("name")]->Value;
ところが,このインターフェースを使用すると,次のようなコードになります。
CustIntf := GetCustomers(XMLDocument1);
CustName := CustIntf[0].Name;
_di_ICustomers CustIntf = GetCustomers(XMLDocument1);
CustName = CustIntf->Nodes->GetNode(0)->Name;
データバインドウィザードが生成したインターフェースはすべて,IXMLNode を継承しています。つまり,データバインドウィザードを使用しない場合と同様に,子ノードの追加と削除ができます。子ノードの追加と削除については,「XML ノードの操作」を参照してください。さらに,(1 つのノードの子がすべて同じ型であるときに)子ノードが繰り返しの要素を表す場合,親ノードには,追加の繰り返しを追加するために Add と Insert の 2 つのメソッドが与えられます。これらのメソッドでは作成するノードの型を指定する必要がないので,AddChild を使用するより簡単です。
以下のトピックでは,XML データバインドウィザードの使い方を説明しています。