9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Delphi XMLデータバインディングを使ってみる

Last updated at Posted at 2014-05-30

はじめに

Delphi の XMLデータバインディング凄い便利!嬉しい! と思ったのですが、ちょっと分からない所があったので、わかった部分を紹介しつつ、疑問点を書いてみたいと思います。

開発環境は Delphi XE3 です。

基本的に、エンバカデロの解説ページを端折って紹介しているので、詳しい情報はそちらを見て頂いた方が良いかと思います。
XML データ バインディング ウィザードを使用する
XML_データバインドウィザードが生成するコードの使い方

使い方

例として、学校の試験成績を記録するXMLファイルを考えてみます。

<TestResult>
	<Student>
		<Id>01234</Id>
		<Name>田中 太郎</Name>
		<Score>
			<Cource>English</Cource>
			<Date>2014/05/30</Date>
			<Value>80</Value>
		</Score>
		<Score>
			<Cource>Mathematics</Cource>
			<Date>2014/05/30</Date>
			<Value>80</Value>
		</Score>
	</Student>
</TestResult>

上記をXMLファイルとして保存しておきます(エンコードは UTF-8 としておきました)。

XMLデータバインディングウィザード

手始めに、新規のフォームアプリケーションを作成します。

次に、ファイル→新規作成→その他 を選択し、ダイアログからXMLデータバインディングを選択します。
新規作成画面

先ほど作成したXMLファイルを、入力し、次へを選択します。
データバインディングウィザード1

ファイル内のタグの整合性に問題が無ければ、タグ要素を解析し、以下のような画面が表示されます。この画面で、タグ要素の取り込み方法を設定できます。

(下画面は、左側のツリーリストで、TestResultTypeをクリックした状態です。)
データバインディングウィザード2

取り込んだXMLファイルには、Student要素が1つしかなかった為、Student要素の繰り返しのチェックがオフになっています。Score要素は予め繰り返し要素となっています。
データバインディングウィザード3

Student要素は、繰り返し有り、と設定を変更しておきます。

テキストデータが入っているタグは、値をどの型で読み取るかを選択できます。
元ファイルに数字で入っていれば、自動でInteger型としてくれます。独自の型に変換したい場合は、一旦Stringとしておき、コード生成後に修正をする事になると思います。
データバインディングウィザード4

要素の設定を確認後、次へをクリックすると、確認画面となります。
データバインディングウィザード5

完了をクリックすると、コードが自動生成されます!
(コード量が多いので割愛)

なお、自動生成されたコードのユニット名は、最初に取込んだXMLファイル名となります。適宜変更して保存してください。

使用してみる

![テスト用フォーム](https://qiita-image-store.s3.amazonaws.com/0/33684/8e562291-a7ec-8227-58b0-8fd59563e20f.png)

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Sample, XMLIntf;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  WriteXml:IXMLTestResultType;
begin
  WriteXml := NewTestResult;
  WriteXml.Add;
  WriteXml.Student[0].Id := 1000;
  WriteXml.Student[0].Name := '佐藤 二郎';
  WriteXml.Student[0].Score.Add ;
  WriteXml.Student[0].Score[0].Date   := Date;
  WriteXml.Student[0].Score[0].Cource := 'English';
  WriteXml.Student[0].Score[0].Value  := 100;
  WriteXml.Student[0].Score.Add ;
  WriteXml.Student[0].Score[1].Date   := Date;
  WriteXml.Student[0].Score[1].Cource := 'Science';
  WriteXml.Student[0].Score[1].Value  := 40;

  Memo1.Lines.Assign(WriteXml.OwnerDocument.XML);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i,j:integer;
  ReadXml:IXMLTestResultType;
  Student: IXMLStudentType;
  Score: IXMLScoreType;
begin
  if OpenDialog1.Execute then begin

    Memo1.Clear;
    ReadXml := LoadTestResult(OpenDialog1.Files[0]);

    for i:= 0 to ReadXml.Count-1 do begin
      Student := ReadXml.Student[i];
      Memo1.Lines.Add('Id:'+IntToStr(Student.Id));
      Memo1.Lines.Add('Name:'+Student.Name);
      for j := 0 to Student.Score.Count-1 do begin
        Score := Student.Score[j];
        Memo1.Lines.Add('  Score('+Score.Cource+') :'+IntToStr(Score.Value) );
      end;
    end;

  end;
end;

end.

実行結果

![オブジェクト作成ボタンを押した時ー](https://qiita-image-store.s3.amazonaws.com/0/33684/2080a6c2-5fe7-b42b-75b3-580e3171241f.png) Button1Clickイベントで作成したオブジェクトがXMLテキストに変換出来ました。嬉しい!

ファイル読み込みボタンを押した時ー
(テストとして、最初にテンプレートとして使用したXMLファイルを読み込みました)
ファイルも無事パース出来ました!嬉しい!

疑問点

Qiita用に作り直している内に起きなくなったエラーも幾つかあり・・そこはまだ切り分けが出来ていません。

for~inが使用できない?

ファイルを読み込んでいる箇所ですが、本当は
for Student in ReadXml do 

と書きかったんですが、GetEnumerater が見つかりませんというコンパイルエラーが。
なにかパーサー側に修正が必要なのかも?

XMLタグの整形はできない?

オブジェクトからXMLテキストを書き出す場面ですが、
WriteXml.OwnerDocument.Options := WriteXml.OwnerDocument.Options +[doNodeAutoIndent];
WriteXml.OwnerDocument.NodeIndentStr := '  ';

と設定しても、WriteXml.OwnerDocument.XML から取得できるXMLテキストには変化が無く。Delphi7 の TXMLDocumentでは出来ていたような気がしたのですが・・。
(テキストエディタで見たときに見辛いだけなので、大きな問題ではないと思いつつ)

おわりに

XMLデータバインディング便利です。抱いて!
9
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?