|
|
第3回 XMLツリーの生成
W3C DOMを使ってXMLツリーを生成するには,子孫要素の内容からルート要素までを生成しては追加していくというボトムアップ方式をとる。一方,LINQでは,XMLツリーそのままの直観的な処理が可能だ。今回は,いろいろなXMLツリー生成処理について見ていこう。
生成処理本稿で生成するXMLツリーでは,プログラムコードとの区別をわかりやすくするため,日本語タグを使っている。文字コードはutf-8だ。 まず,新規XMLツリーの生成手順から見ていこう。 1.1からのXMLツリーの生成LINQでは,宣言型の関数型構築(第1回リスト4参照)や,XMLリテラル(第1回リスト5参照)によって,ツリーを生成できる。次のようなコード(リスト1)に,要素名や要素の内容(データ)を当てはめるだけでよい。記述する位置や,カッコさえ間違えなければ,すぐに生成処理を実装できるだろう。
リスト1を理解したうえで,2個の要素を持つ親要素が繰り返す,リスト2のような構造のXMLツリーを生成してみよう。
ここでは,「品名」「単価」用の入力ボックスを2個用意し,データを入力して[OK]ボタンをクリックすると,ツリーが生成されるようにする。XML用のデータ入力と,生成したツリーを表示して確認する領域を設けるため,TextBoxコントロールを3個と,[OK]ボタン用のButtonコントロールを1個使っている。 また,入力された価格を検証するため,CustomValidatorコントロールを,「うどん単価」のデータを入力するTextBox2コントロールの横にレイアウトしている。CustomValidatorコントロールは,標準の検証コントロールでは対応できない独自の検証ロジックを実装するためのコントロールだ。 いくつかのデータを入力して生成したツリーは,図1のようになる。なお,本稿の目的はLINQクエリーの紹介にあるので,基本的に,表示結果とaspx.vbのコードのみ掲載して説明していく。
この処理のポイントは,新規生成の場合と,XMLツリーが生成済みの場合の条件分岐処理を書き分けることだ。一度XMLツリーが生成された後は,既存のXMLファイルを読み込んで,生成済みのルート要素以下に追加しなければならないからだ。 ツリー生成処理のコードは,リスト3のようになる。一見複雑そうに見えるのは分岐処理を書いているからであって,生成処理自体は簡単だ。
(1)ImportsメソッドでSystem.IO名前空間を読み込む。この名前空間はファイルの入出力に関するクラスを提供する。(2)のFile.ExistsでApp_Dataフォルダ内に,任意のファイルが存在しているかどうかをチェックしているため,この名前空間の読み込みが必要になる。 (2)App_Dataフォルダ内に,udons_makeXml.xmlというファイルが存在すれば,XDocument.Loadメソッドで,このファイルを読み込み,TextBox3コントロール内にXMLを表示する。 (3)(6)で定義しているCustomValidatorの,単価が数値であるかどうかを検証するプロシジャで,ページの検証が成功した場合(入力されたデータが数値であった場合),単価を入力するTextBox2の内容(単価を入力するTextBox)が空ではなかった場合の処理を記述している。 (4)生成されたXMLが表示されるTextBox3コントロール内が空であった場合,つまり,はじめてXMLが生成される場合は,XMLの宣言とルート要素(<商品情報>),ルート要素の子要素となる<商品>要素,それに各TextBoxに入力されたデータをもとに,<品名>と<価格>のXMLを新規に生成する(生成手順はリスト1の基本のコードを参照)。 生成されたXMLをSaveメソッドで保存し,同時にTextBox3コントロールにも生成したXMLツリーを表示する。TextBox3に表示されるXMLツリーにはXML宣言は表示されないが,保存した場合は,きちんとXML宣言が付く。 (5)TextBox3コントロールに,生成済みのXMLツリーが表示されている場合,つまり,App_Dataフォルダ内にudons_makeXml.xmlというファイルが存在する場合の処理。まず,XElement.LoadでXMLファイル(udons_makeXml.xml)を読み込む。 New XElementで,<商品>要素と各TextBoxに入力されたデータを内容に,<品名>と<価格>要素を生成する。読み込んだXMLに,Addメソッドで,生成したXMLを追加する。追加されたXMLをSaveメソッドで保存し,同時にTextBox3コントロール内に表示する。 ここで注意しなければならないのは,既存のXML文書を読み込んでデータを追加する場合は,XElement.Loadで読み込むことだ,XDocument.Loadでルート要素まで読み込んでしまうと,整形式ではない文書になってしまい,エラーが発生するので注意しよう。 (6)この部分のコードはLINQとは直接関係はないが,CustomValidatorで利用する,価格に入力されたデータが数値かどうかを検証する処理だ。 検証対象となる入力コントロールの値には,検証メソッドのパラメータとして渡されるServerValidateEventArgsオブジェクトのValueプロパティを介してアクセスする。e.Valueで,単価を入力するTextBox2コントロールに入力された値を取得できる。 IsNumeric関数で数値かどうかを判別する。数値ならTrue,それ以外はFalseを返す。IsValidプロパティで検証が成功したかどうかを判別する。e.Isvalid=Trueなら検証は成功,e.IsValid=Falseなら検証は失敗となる。ここでは,CustomValidatorのコードとしてprice_checkプロシジャを定義している。 このプロシジャをCustomValidatorのイベントに関連付けるには,価格を入力するTextBox2コントロールの横にレイアウトしたCustomValidatorコントロールを選択してプロパティを表示し,上方にある「稲妻」アイコンをクリックしてイベントを表示させる。ServerValidateイベントの横のドロップダウンリストをクリックすると,price_checkプロシジャの名前が表示されるので,これを選択する(図2,表1)。
表1●CustomValidatorのプロパティ
>>2.要素と属性の生成
連載新着連載目次へ >>
|