「ソフテックだより」では、ソフトウェア開発に関する情報や開発現場における社員の取り組みなどを定期的にお知らせしています。
さまざまなテーマを取り上げていますので、他のソフテックだよりも、ぜひご覧下さい。
ソフテックだより(発行日順)のページへ
ソフテックだより 技術レポート(技術分野別)のページへ
ソフテックだより 現場の声(シーン別)のページへ
Windowsアプリケーション開発におけるシステム設計フェーズでは、「システムで使用するデータをどのように管理するか?」を決める必要があります。
弊社では、.NET Frameworkアプリケーション開発を手がける機会が増えており、それに伴ってシステム管理データを扱うファイル形式にXML形式ファイルを利用する機会も多くなっています。
今回のメルマガでは、 XML形式ファイルの概要と.NET Framework開発言語(C#)からXMLを操作する方法についてご紹介させていただきます。
XML(Extensible Markup Language)形式ファイルは世界標準となっている、簡単なデータの保存、交換に便利な規格です。
XML形式ファイルは以下のような特徴をもっています。
今回の技術レポートでは、XMLの特徴として挙げられる(1)〜(3)に着目して、XML形式ファイルのシステム利用について取り上げます。
XMLファイルでは、個々のデータ(要素)を“タグ”を用いたツリー構造で表すことができます。タグは自由に設定することができ、データに対して意味や構造を保持することが可能なため、多様なデータ構造を分かり易く表すことに適しています。
以下に、社員情報のデータを扱う場合のXML形式データの例を示します。
<?xml version="1.0"
encoding="utf-8"?>
<社員情報リスト
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<社員情報>
<社員番号>1234</社員番号>
<部署>技術部</部署>
<氏名>
<苗字>XX</苗字>
<名前>XXX</名前>
</氏名>
<連絡先>
<住所>東京都XXXXXXXXX</住所>
<電話番号>030-xxxx-xxxx</電話番号>
<携帯番号>090-xxxx-xxxx</携帯番号>
</連絡先>
</社員情報>
<社員情報>
<社員番号>4567</社員番号>
・・・
</社員情報>
・・・
・・・
</社員情報リスト>
1. 社員情報を表すXML形式データ例
上記、XML形式データの例を確認すると分かると思いますが、データ構造がデータベースと同様の構造を持っており、仕様変更や異なるシステム間でのデータ交換に柔軟に対応できるメリットがあります。
XML形式ファイルのデータは、データベースが使用できない環境で、同形式のデータを管理したい場合に適したシステムへの利用方法となります。
システム間でデータをやり取りする場合、XMLファイルと同様にテキスト形式で記述されるファイル形式に、CSV(Comma-Separated Values)ファイルがあります。
CSVファイルを利用する場合は、データ構造をファイルフォーマットという形で規定して「目的の***の情報は、何レコード目(行)の何番目(列)に情報がある」という前提で目的とするデータにアクセスします。
以下に、「3. XML形式データ構造について」で表現した社員情報のデータをCSV形式データ扱う場合の例を示します。
;社員番号,部署,氏名(姓),氏名(名),連絡先(住所),…
1234,技術部,XX,XXX,東京都XXXXXXXXX,・・・
4567,・・・
図2. 社員情報を表すCSV形式データ例
XMLファイルと比較した時にCSVのデータ構造は、カンマで区切られたデータ集合であるため仮に“1234”というデータが存在した時にそのデータが何であるか直感的ではありません。また、XML形式データが特定のタグ情報を省略(データが存在しなくてもエラーとしない)できるのに対して、CSV形式の場合は省略させることができない点もデメリットに感じます。
また、仕様変更でデータ構造に変更(データの追加)を要す場合、XML形式であればタグの追加で記述すれば仕様変更に柔軟に対応できるのに対して、CSV形式の場合はデータが追加された位置によって順番が影響を受けることになります。
例えば、社員情報の中の“社員番号”の後のフィールドに、それぞれ“入社年月”を追加するケースを想定した場合を例に比較してみます。
<社員情報>
<社員番号>1234</社員番号>
<入社年月>2000_04</入社年月>
<部署>技術部</部署>
・・・
・・・
</社員情報>
図3. XML形式データ内容の変更例
;社員番号,入社年月,部署,氏名(姓),氏名(名),連絡先(住所),…
1234,2000_04,技術部,・・・
図4. CSV形式データ内容の変更例
この違いは、そのままプログラミングで実装する処理の違いとして現れます。CSV形式を利用する場合には、データ構造に変更が入る度にファイルフォーマットに変更が生じて、何番目(列)以降のデータの意味が変わる場合などには、「予めファイルバージョンのような情報を持たせておいて、ファイルバージョンに応じてデータアクセス位置を変える」などの実装が必要になってきます。
一方、XML形式であればタグ名でデータをアクセスするようにできるため、新たなデータ(タグ、要素)を追加してもプログラム修正を少なく済ませることができます。
CSV形式を比較対照として、データ構造を比較してみましたが、タグを使って記述するXML形式がシステム変更に柔軟に対応できる利点をもったファイルフォーマットであることがご理解いただけると思います。
.NET Framework開発言語(C#)では、開発環境に用意された標準クラス群が提供するXML操作機能を利用することによって、簡単にXML形式ファイルを扱うことが可能です。
オブジェクト指向に基づきデータ構造をモデリングしたクラスや構造体をXML形式ファイルにシリアライズ/デシリアライズ(保存/読込)するXmlSerializerクラスを利用する例をご紹介します。
XmlSerializerクラスは、オブジェクトデータ構造でXMLファイルの作成/読み込み処理を実装できるため、従来のCSVファイルを利用していた時の読み込み処理、保存処理の対応負荷がまるまる軽減することができます。
図5. XmlSerializerクラスを用いたファイル読込/保存実装イメージ
(1). オブジェクトデータ(クラス / 構造体)の定義
XmlSerializerクラスのシリアライズ/デシリアライズ対象は、オブジェクトのpublicで規定された読み取り専用属性でないプロパティに限定されます。
///<summary>社員情報</summary>
[XmlRoot("社員情報リスト")]
public class EmployeeInfoList
{
[XmlElement("社員情報")]
public List<EmployeeInfo> list = new
List<EmployeeInfo>();
}
///<summary>氏名情報</summary>
publicstruct NameInfo
{
[XmlElement("苗字")]
public String
family;
[XmlElement("名前")]
public String
name;
}
///<summary>連絡先情報</summary>
publicstruct ContactInfo
{
[XmlElement("住所")]
public String
addr;
[XmlElement("電話番号")]
public String
phone;
[XmlElement("携帯番号")]
public String
portable;
}
図6. オブジェクトデータ(クラス/構造体)の定義
(2). XMLファイル読み込み
XMLSerealizerクラスのデシリアライズ機能を使用して、(1)で定義したオブジェクトにXMLファイルの情報を読み込む例を示します。読み込むXMLファイルの構造は、定義したデータ構造と合っている必要があります。
///<summary>
/// ボタン1押下イベント
/// XMLファイル読み込み処理を行う
///</summary>
privatevoid
button1_Click(object sender, EventArgs e)
{
// ファイルパス(カレントディレトリ直下のText.xml固定)
String filepath = String.Format("{0}\\test.xml", Application.StartupPath);
StreamReader sr = null;
XmlSerializer xs = null;
EmployeeInfoList target = null;
String err = "";
// XMLファイル読み込み(XmlSerializerによるデシリアライズ)
try
{
//ファイル読み込みインスタンス作成
sr =
new StreamReader(filepath, Encoding.UTF8);
//XMLシリアライザクラスインスタンス作成
xs =
new XmlSerializer(typeof(EmployeeInfoList));
//XMLファイルデシリアライズ
target
= (EmployeeInfoList)xs.Deserialize(sr);
}
catch (Exception
exp)
{//例外発生
err = exp.Message;
}
finally
{//インスタンス破棄
if (sr != null)
{
sr.Close();
sr.Dispose();
}
}
}
図7. XmlSerializerクラスのファイル読込 実装方法例
(3). XMLファイル書き込み
XMLSerealizerクラスのシリアライズ機能を使用して、(1)で定義したオブジェクト情報をXMLファイル保存する例を示します。
///<summary>
/// ボタン2押下イベント
/// XMLファイル保存処理を行う
///</summary>
privatevoid button2_Click(object
sender, EventArgs e)
{
// 社員情報登録データ作成
EmployeeInfo tmp;
tmp.no = 1234;
tmp.part = "技術部";
tmp.name.family = "姓";
tmp.name.name = "名";
tmp.contact.addr = "東京都XXXXXXXXX";
tmp.contact.phone = "030-xxxx-xxxx";
tmp.contact.portable = "090-xxxx-xxxx";
// 社員情報リストインスタンス作成
EmployeeInfoList target = new
EmployeeInfoList();
// リストにデータを登録
target.list.Add(tmp);
// ファイルパス(カレントディレトリ直下のText.xml固定)
String filepath = String.Format("{0}\\test.xml", Application.StartupPath);
XmlTextWriter xtw = null;
XmlSerializer xs = null;
String err = "";
// XMLファイル保存
try
{
//XMLファイル書き込みインスタンス作成
xtw = new XmlTextWriter(filepath,
Encoding.UTF8);
xtw.Formatting = Formatting.Indented;
xtw.Indentation = 4;
//XMLシリアライザクラスインスタンス作成
xs = new XmlSerializer(typeof(EmployeeInfoList));
//XMLファイルシリアライズ
xs.Serialize(xtw,
target);
}
catch (Exception
exp)
{//例外発生
err = exp.Message;
}
finally
{//インスタンス破棄
if (xtw != null)
{
xtw.Close();
}
}
}
図8. XmlSerializerクラスのファイル保存 実装方法
冒頭でXML形式データの特徴として挙げましたように、XMLは汎用のデータ記述言語として優れた特徴を持っています。反面、XML形式データのデメリットとしては、タグによってデータ(要素)がマークアップされるため、膨大なデータを扱う場合にはバイナリ形式(独自形式)の方がパフォーマンス面で優位性があります。XML形式のファイルをシステムで利用する際には、XMLの特徴を理解した上で導入することが肝要です。
いずれにしても、データ構造のメンテンナンス性を向上させたい場合や、特定のデータのみ取り出したり、異なるシステム間でデータのやり取りする場合にはシステムへのXMLファイルの導入を検討する価値はあると思います。
今回のメルマガで取り上げさせていただいた内容がXML形式ファイルのシステム導入をご検討いただく際の検討材料のひとつになれば幸いです。
関連した技術にXMLデータ構造を規定するXML Schemaや、XLSスタイルシートとCSS(Cascading Style Sheet)を用いてXMLデータから必要な情報を取り出して表示・印刷レイアウトの書式を指定する方法など、横展開した技術が存在しますので、本技術レポートのテーマで取り上げてみたいと思います。
(M.S.)
関連ページへのリンク
関連するソフテックだより