第 6 回 : 実践 XML (SVG)
〜 Visual C# による XML チュートリアル 〜
6.1 はじめに
XML は、文書の意味や論理構造を自由に定義や拡張し、Web 上で手軽に使用できます。そのため、XML を用いて文書構造を定義したサブセット (subset) 言語が数多く存在します。例えば、数式データを定義した MathML やマルチメディアデータを定義した SMIL があります。XML は、文書の構造を定義するためのものであり、実際の業務で XML を利用する場合には、目的に応じたサブセットと、そのサブセットを扱うアプリケーションが必要となります。そこで、本章では、XML のサブセット言語の中でも、業界標準としての位置を確立している SVG (Scalable Vector Graphics) に注目します。SVG は、XML 形式のテキストで記述されたベクター・グラフィックフォーマットです。本章では、SVG の概要について解説し、簡易 SVG エディタの作成を行います。簡易 SVG エディタとは、直線、四角形、円の描画を行い、描画内容を SVG 文書として出力するプログラムです。前半では、SVG の概要について説明し、後半では、Visual C# .NET による簡易 SVG エディタの作成方法について解説します。
6.2 SVG の概要
6.2.1 SVG の概要
SVG (Scalable Vector Graphics) は、2001 年 9 月に W3C において勧告された XML サブセットのベクター・グラフィックス言語です。従来、Web 上で利用されていたグラフィックスは、GIF や JPEG といったラスター (ビットマップ) 形式が主流でした。しかし、ラスター・グラフィックスでは、表示する画像の画素情報がすべて必要であるため、ファイルサイズが大きくなるという欠点があります。また、Web 上で利用するグラフィックスには、標準となるベクター形式が存在しませんでした。そこで、1998 年、W3C は、ベクター・グラフィックスの標準を策定するために、VML (Vector Markup Language) および PGML (Precision Graphics Markup Language) を提案しました。そして、議論の末、SVG は、VML と PGML の優れた部分を取り入れる形で開発されました。SVG の概要を図 1 に示します。

図 1 SVG の概要
SVG の特徴は、まず、XML ベースであることが挙げられます。SVG は、テキストエディタで編集が可能であり、メタデータの付加も容易です。そのため、SVG は、サーチエンジンからの検索やサーバサイドでの自動生成が可能です。次に、多様なグラフィック機能が用意されていることが挙げられます。具体的には、グラデーションや透明度の設定をするフィルタ機能、表示スタイルを統括的に定義するスタイル機能、画像に動きを付加するアニメーション機能があります。また、SVG では、約 1600 万色を使用できます。最後に、ベクター形式であることが挙げられます。ベクター・グラフィックスは、画像の情報をベクトルで扱うため、画像サイズに関わらずファイル容量がほぼ一定です。また、ベクター・グラフィックスは、拡大した画像も鮮明に表示できます。SVG は、軽量なフォーマットであり、画像の拡大に対応できます。SVG の特徴を図 2 に示します。

図 2 SVG の特徴
SVG は、グラフィックを定義したデータ形式です。SVG を操作するには、SVG アプリケーションの利用が不可欠です。そのため、現在、SVG に関連した様々なアプリケーション開発が進められています。
6.2.2 SVG 文書の構成
SVG 文書は、XML 宣言、DTD (Document Type Definition)、SVG 文書要素より構成されます。XML 宣言では、この文書が XML 文書であることを宣言します。DTD では、SVG 文書の文書構造を定義します。SVG 文書要素では、DTD で定義された文書構造に従い、内容を記述します。SVG 文書の例を次に示します。
<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg>
<line x1="38" y1="55" x2="224" y2="32" style="stroke:blue" />
<rect x="34" y="118" width="79" height="67" style="fill:red; stroke:red;" />
<circle cx="207" cy="146" r="46" style="fill:yellow; stroke:yellow;" />
</svg>
|
 |
上記の SVG 文書の表示例を図 3 に示します。

図 3 SVG 文書の表示例
(1) XML 宣言
XML 宣言では、XML 文書であることを示すために、XML のバージョン、文字コード、Standalone 文書宣言を指定します。SVG 文書の XML 宣言は、XML 文書と同様です。詳しくは、第 1 回 XML の概要、第 1.2.3 項を参照してください。
(2) DTD
DTD では、SVG 文書の文書型定義を指定します。SVG 文書の DTD は、W3C が公開しているものを参照します。そのため、DTD には、参照のための識別子が記述されます。SVG 文書の DTD を以下に示します。
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
(3) SVG 文書要素
SVG 文書要素では、描画するオブジェクトを記述します。描画するオブジェクトは、一つ一つが SVG 文書の要素となっており、属性に座標情報や色などのスタイル情報を指定します。SVG 文書要素は、数多く存在するため、ここでは、基本オブジェクトとなる line 要素 (直線)、rect 要素 (四角形)、circle 要素 (円) とスタイル情報を定義する style 属性について解説します。SVG 文書要素の記述方法は、XML 文書要素の記述方法と同様です。詳しくは、第 1 回 XML の概要、第 1.2.3 項を参照してください。
SVG 文書要素では、必ず svg 要素がルート要素になります。svg 要素では、主に描画するオブジェクトの表示領域を指定します。主な svg 要素の属性を表 1 に示します。
表 1 主な svg 要素の属性
| 属性名 | 説明 |
| width | 表示領域の幅を指定する |
| height | 表示領域の高さを指定する |
svg 要素の記述例を以下に示します。
<svg width="800" height="600" />
line 要素は、直線を描画するための要素です。直線を描画するには、始点の座標と終点の座標を指定します。主な line 要素の属性を表 2 に示します。
表 2 主な line 要素の属性
| 属性名 | 説明 |
| x1 | 始点の X 座標を指定する |
| y1 | 始点の Y 座標を指定する |
| x2 | 終点の X 座標を指定する |
| y2 | 終点の Y 座標を指定する |
line 要素の記述例を以下に示します。
<line x1="50" y1="50" x2="200" y2="200" />
rect 要素は、四角形を描画するための要素です。四角形を描画するには、始点の座標と始点からの幅と高さを指定します。主な rect 要素の属性を表 3 に示します。
表 3 主な rect 要素の属性
| 属性名 | 説明 |
| x | 始点の X 座標を指定する |
| y | 始点の Y 座標を指定する |
| width | 四角形の幅を指定する |
| height | 四角形の高さを指定する |
rect 要素の記述例を以下に示します。
<rect x="10" y="10" width="200" height="100" />
circle 要素は、円を描画するための要素です。円を描画するには、中心点の座標と半径を指定します。主な circle 要素の属性を表 4 に示します。
表 4 主な circle 要素の属性
| 属性名 | 説明 |
| cx | 中心点の X 座標を指定する |
| cy | 中心点の Y 座標を指定する |
| r | 半径を指定する |
circle 要素の記述例を以下に示します。
<circle cx="100" cy="100" r="50" />
style 属性は、オブジェクトにスタイル情報を定義します。例えば、オブジェクトの色や線の種類などを定義します。主な style 属性の値を表 5 に示します。
表 5 主な style 属性の値
| 値 | 説明 |
| fill | オブジェクトに色をつける |
| stroke | 線に色をつける |
style 属性の記述例を以下に示します。
<circle cx="100" cy="100" r="50" style="fill:red; stroke:red;" />
6.3 簡易 SVG エディタの作成
本節では、実際に簡易 SVG エディタの作成を行います。簡易 SVG エディタとは、直線、四角形、円の描画を行い、描画内容を SVG 文書として出力するプログラムです。簡易 SVG エディタの作成手順は、新しいプロジェクトの作成、インタフェースの作成、ソースコードの追加です。
(1) 新しいプロジェクトの作成
最初に、新しいプロジェクトを作成します。新しいプロジェクトの作成には、メニューから 【ファイル】 → 【新規作成】 → 【プロジェクト】 を選択します。次に、【Visual C# プロジェクト】 → 【Windows アプリケーション】 を選択します。最後に、プロジェクト名と保存場所を指定し、【OK】 ボタンを押します。
(2) インタフェースの作成
次に、Visual C# .NET のデザイン画面よりプログラムのインタフェースを作成します。簡易 SVG エディタのインタフェースを図 4 に示します。

図 4 簡易 SVG エディタのインタフェース
ただし、PictureBox コントロールの BackColor プロパティを「White」、BorderStyle プロパティを「Fixed3D」に設定します。
(3) ソースコードの追加
次に、ソースコードを追加します。まず、XML 文書を操作するため、Form1 のソースコードへ XML 名前空間の参照を追加します。XML 名前空間の参照を図 5 に示します。

図 5 XML 名前空間の参照
次に、SVG 文書作成のため、XmlTextWriter クラスのインスタンスを生成します。XmlTextWriter クラスは、DOM を生成することなく XML 文書をファイルに出力することができます。XmlTextWriter クラスのインスタンス生成コードを図 6 に示します。

図 6 XmlTextWriter クラスのインスタンス生成コード
次に、グラフィックを描画するため、Graphics オブジェクトの作成と Pen クラスのインスタンス生成を行います。Graphics オブジェクトの作成と Pen クラスのインスタンス生成コードを図 7 に示します。

図 7 Graphics オブジェクトの作成と Pen クラスのインスタンス生成コード
次に、変数を定義します。変数の定義コードを図 8 に示します。

図 8 変数の定義コード
次に、Form1 _Load イベントハンドラへコードを記述します。Form1 をダブルクリックし、コードを追加します。Form1 _Load イベントハンドラに記述するコードを次に示します。
private void Form1_Load(object sender, System.EventArgs e)
{
myGraphics = pictureBox1.CreateGraphics(); // pictureBox1への参照を取得
Svg.Formatting = Formatting.Indented; // SVG文書のフォーマットを設定
Svg.WriteStartDocument(); // SVG文書の作成
// DTDの作成
Svg.WriteDocType("svg","-//W3C//DTD SVG 20010904//EN",
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd",null);
Svg.WriteStartElement("svg"); // ルート要素の作成
}
次に、button1_Click イベントハンドラおよび button2_Click イベントハンドラ、button3_Click イベントハンドラ、button4_Click イベントハンドラへコードを記述します。Form1 に作成した button1 コントロールおよび button2 コントロール、button3 コントロール、button4 コントロールをそれぞれダブルクリックし、コードを追加します。各ボタンのイベントハンドラに記述するコードを次に示します。
private void button1_Click(object sender, System.EventArgs e) // 直線ボタン
{
sObjectname = "line"; // オブジェクト名に「line」を格納
}
private void button2_Click(object sender, System.EventArgs e) // 四角形ボタン
{
sObjectname = "rect"; // オブジェクト名に「rect」を格納
}
private void button3_Click(object sender, System.EventArgs e) // 円ボタン
{
sObjectname = "circle"; // オブジェクト名に「circle」を格納
}
private void button4_Click(object sender, System.EventArgs e) // 保存ボタン
{
Svg.WriteEndElement(); // SVG 文書への要素追加終了
Svg.WriteEndDocument(); // SVG 文書作成完了
Svg.Flush(); // SVG 文書をフラッシュ
Svg.Close(); // SVG 文書を閉じる
}
次に、pictureBox1_MouseDown イベントハンドラおよび pictureBox1_MouseUp イベントハンドラへコードを記述します。pictureBox1_MouseDown イベントハンドラを作成するには、pictureBox1 のプロパティより MouseDown イベントを選択し、イベントハンドラ名を pictureBox1_MouseDown に指定します。また、同様の手順で pictureBox1_MouseUp イベントハンドラを作成します。イベントハンドラの作成方法を図 9 に示します。

図 9 イベントハンドラの作成方法
作成した pictureBox1_MouseDown イベントハンドラおよび pictureBox1_MouseUp イベントハンドラへコードを追加します。pictureBox1_MouseDown イベントハンドラおよび pictureBox1_MouseUp イベントハンドラのコードを次に示します。
private void pictureBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{ // pictureBox1 上でマウスのボタンが押された場合
iStartX = e.X; // 押された場所のX座標を iStartX へ格納
iStartY = e.Y; // 押された場所のY座標を iStartY へ格納
}
private void pictureBox1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{ // pictureBox1上でマウスのボタンが離された場合
iEndX = e.X; // 離された場所の X 座標を iEndX へ格納
iEndY = e.Y; // 離された場所の Y 座標を iEndY へ格納
if(sObjectname == "line")
drawline(); // sObjectname が line ならば drawline() を実行
else if(sObjectname == "rect")
drawrect(); // sObjectname が rect ならば drawrect() を実行
else if(sObjectname == "circle")
drawcircle(); // sObjectname が circle ならば drawcircle() を実行
}
最後に、drawline (直線描画) およびdrawrect (四角形描画)、drawcircle (円描画) 関数のコードを追加します。drawline および drawrect、drawcircle 関数のコードを次に示します。
private void drawline() // 直線の描画と line 要素の記述
{
myGraphics.DrawLine(myPen,iStartX,iStartY,iEndX,iEndY); // 直線の描画
Svg.WriteStartElement("line"); // line要素の記述開始
Svg.WriteAttributeString("x1",Convert.ToString(iStartX)); // x1 属性の記述
Svg.WriteAttributeString("y1",Convert.ToString(iStartY)); // y1 属性の記述
Svg.WriteAttributeString("x2",Convert.ToString(iEndX)); // x2 属性の記述
Svg.WriteAttributeString("y2",Convert.ToString(iEndY)); // y2 属性の記述
Svg.WriteAttributeString("style","stroke:blue"); // style 属性の記述
Svg.WriteEndElement(); // line 要素の記述終了
}
private void drawrect() //四角形の描画と rect 要素の記述
{
// 四角形の描画
myGraphics.DrawRectangle(myPen,iStartX,iStartY,
Math.Abs(iEndX-iStartX),Math.Abs(iEndY-iStartY));
Svg.WriteStartElement("rect"); // rect 要素の記述開始
Svg.WriteAttributeString("x",Convert.ToString(iStartX)); // x 属性の記述
Svg.WriteAttributeString("y",Convert.ToString(iStartY)); // y 属性の記述
// width属性の記述
Svg.WriteAttributeString("width",Convert.ToString(Math.Abs(iEndX-iStartX)));
// height属性の記述
Svg.WriteAttributeString("height",Convert.ToString(Math.Abs(iEndY-iStartY)));
Svg.WriteAttributeString("style","fill:white; stroke:blue;"); // style属性の記述
Svg.WriteEndElement(); // rect属性の記述終了
}
private void drawcircle() // 円の描画と circle 要素の記述
{
// 円の半径を計算し,double 型の r へ格納
double dR = Math.Sqrt(Math.Pow(iEndX-iStartX,2) + Math.Pow(iEndY-iStartY,2));
int iR = (int)dR; // double型のdRをint型に変換しiRへ格納
myGraphics.DrawEllipse(myPen,iStartX-iR,iStartY-iR,iR*2,iR*2); // 円の描画
Svg.WriteStartElement("circle"); // circle要素の記述開始
Svg.WriteAttributeString("cx",Convert.ToString(iStartX)); // cx 属性の記述
Svg.WriteAttributeString("cy",Convert.ToString(iStartY)); // cy 属性の記述
Svg.WriteAttributeString("r",Convert.ToString(iR)); // r 属性の記述
Svg.WriteAttributeString("style","fill:white; stroke:blue;"); // style 属性の記述
Svg.WriteEndElement(); // circle 属性の記述終了
}
(4) 簡易 SVG エディタの実行
最後に、簡易 SVG エディタを実行します。簡易 SVG エディタは、描画したオブジェクトを SVG ファイルに出力するプログラムです。簡易 SVG エディタは、直線、四角形、円を描画し、描画結果を SVG ファイルとして出力します。ユーザは、描画するオブジェクトをボタンで選択し、マウスのクリックによりキャンパスへ描画します。簡易 SVG エディタの実行画面を図 10 に示します。

図 10 簡易 SVG エディタの実行画面
SVG 文書は、【作成したプロジェクトのフォルダ】 → 【binフォルダ】 → 【Debugフォルダ】 にファイル名「sample.svg」で保存されます。
出力した SVG 文書をメモ帳で表示します。出力した SVG 文書の表示例を図 11 に示します。

図 11 出力した SVG 文書の表示例
6.4 まとめ
本章では、XML のサブセット言語である SVG を取り上げ、SVG の概要について解説し、簡易 SVG エディタの作成を行いました。XML は、文書の構造を定義するためのものであり、実際の業務で XML を利用する場合には、目的に応じたサブセットと、そのサブセットを扱うアプリケーションが必要となります。.NET Framework には、XML を操作するためのクラスが豊富に用意されています。これらのクラスを利用することにより、XML のサブセット言語を対象としたアプリケーション開発において、作業量を大幅に削減し、高い生産性を実現できます。
著者紹介
田中 成典 (たなか しげのり)
| 1986年 | 関西大学工学部土木工学科卒業 |
| 1988年 | 関西大学大学院工学研究科 土木工学専攻博士課程前期課程修了 |
| 1996年 | 博士 (工学) 授与,関西大学 |
| 1997年 | 関西大学総合情報学部助教授 (現在に至る) |
| 主な著書: | やさしいCのはじめかた,オーム社,1993年 |
| | 建設技術者のための知識情報処理の実践,関西大学出版部,1999年 |
| | DirectX8,工学社,2001年 |
| | ステップアップXML,工学社,2002年 |
| | Linuxアプリケーション入門,森北出版,2002年 ほか |
中山 浩太郎 (なかやま こうたろう)
| 2001年3月 | 関西大学総合情報学部卒業 |
| 2001年4月 | 関西大学大学院総合情報学研究科入学 (現在に至る) |
| 2002年4月 | 同志社女子大学非常勤講師 (現在に至る) |
| 主な著書: | Web工房シリーズ Perlの達人,森北出版,1999年 |
| | DirectX8,工学社,2001年 |
| | Linuxアプリケーション入門,森北出版,2002年 ほか |
石井 健一 (いしい けんいち)
| 1999年4月 | 関西大学総合情報学部総合情報学科入学 (現在に至る) |
| 主な著書: | ステップアップXML活用法,工学社,2002年 |
野中 一希 (のなか かずき)
| 1999年4月 | 関西大学総合情報学部総合情報学科入学 (現在に至る) |
| 2002年1月 | 株式会社関西総合情報研究所入社 (現在に至る) |
中村 健二 (なかむら けんじ)
| 2000年4月 | 関西大学総合情報学部総合情報学科入学 (現在に至る) |
| 2002年4月 | 株式会社関西総合情報研究所入社 (現在に至る) |
|