EasyXml by kanegon 1. 概要 DOM や SAX などの一般的なXML操作インタフェースは多機能で矛盾がないように設計さ れ、それなりに使いやすいものになっている。 とはいうものの、それは数十あるいは数百もの機能をフルに使うために十分に整理され ているというだけであって、Windows の .ini ファイルやあるいはJava の .properties ファイルの操作メソッドと同じように簡単というわけではない。 機能の絶対量が違うためである。 このことは XML データそのものが重要な用件であれば問題にならない程度のものだが、 30分で作成するような簡単なツールの設定ファイルとして XML を使うような局面では 面倒なものとなる。 なぜなら、このような簡単なツールの設定ファイルとして使う場合、テキストまたは 属性値の設定または取得ができればそれ以上の機能はほとんど必要としないが、その アクセスのために2ステップ以上の手順が必須とされることが多いためである。 とはいえ、階層構造を表現でき、他のツールとの親和性の高い XML の利点は捨てがた い。 というわけで、EasyXml は XML を操作するための機能を絞り込み、十分に簡単で実用 的な XML ライブラリを目指すものである。 実装は既存の MSXML の簡単なラッパとして作成する。 とりあえず JavaScript(JScript) および C# 版を提供する。 今後も対応言語は増やしていく予定。 C# の説明は cs/readme.txt を参照のこと。 2. 環境 以下の環境で確認している。 その他の環境でも動作するはずだが、確認できていない。 Windows 2000 pro SP4 Windows XP SP1 この他、MSXML が必要だが MSXML は IE に含まれているため、通常気にする必要は ない。 3. ファイル構成 readme.txt このファイル common.js 低レベル共通ライブラリ easyxml.js XML ライブラリ本体 test.wsf 使い方サンプル msxml_constant.js MSXML 定数宣言 (参考) ライブラリとして必要なものは easyxml.js と common.js の2つである。 test.wsf がライブラリの使用例となっている。 4. 特徴 簡単な例を挙げて、既存処理(MSXML をそのまま使う)と比較してみる。 4.1 対象とする XML これを生成すると仮定する。 z1 z2 4.2 既存の操作 MSXML をそのまま使う方法である。 try { var xml = new ActiveXObject("Msxml2.DOMDocument"); xml.async = false; var pi = this.xml.createProcessingInstruction("xml", "version='1.0' encoding='Shift_JIS'"); xml.appendChild(pi); var root = xml.createElement("rootElement"); xml.appendChild(root); var x = xml.createElement("x"); root.appendChild(x); var yy = xml.createElement("yy"); x.appendChild(yy); var z1 = xml.createElement("z1"); yy.appendChild(z1); z1.text = "z1"; var z2 = xml.createElement("z2"); yy.appendChild(z2); z2.text = "z2"; var z3 = xml.createElement("z3"); yy.appendChild(z3); z3.setAttribute("attr1", "value1"); z3.setAttribute("attr2", "value2"); xml.save("text.xml"); } catch (e) { // error } これは決して難しいものではない。しかし、たかが設定ファイルの読み書きに使 いたいものでもない。 しかも、この結果は z1z2 とインデントされずに保存される。 4.3 当ライブラリによる操作 try { var xml = new EasyXml(); xml.setRoot("rootElement"); xml.setText("x/yy/z1", "z1"); xml.setText("x/yy/z2", "z2"); xml.setAttribute("x/yy/z3", "attr1", "value1"); xml.setAttribute("x/yy/z3", "attr2", "value2"); xml.save("test.xml", "Shift_JIS"); } catch (e) { // error } 4.2 の記述に比べてかなり単純化される。 結果は 2.1 の例のとおりにインデント付きで保存される。 これなら、簡単なツールの設定ファイルの読み書き用としても使う気になる。 5. クラス概要 ライブラリは JavaScript のクラス(もどき)で提供される。 以下にクラスの構成を Java のクラス風に記述してみる。 JavaScript の実際の文法とは異なるので注意のこと。 また、主に内部使用を目的とするメソッドは除外して説明する。 class EasyXml { // コンストラクタ EasyXml([String filename]); // 初期化 void clear(); // sertter/getter、要素取得、要素追加、など void setRoot(String text); String getRoot(); node findNode(String location[, node base]); void setNode(String location[, node base]); node getNode(String location[, node base]); void setText(String location, String text[, node base]); String getText(String location[, node base]); void setAttribute(String location, String attrName, String attrValue[, node base]); String getAttribute(String location, String attrName[, node base]); node addNode(String parent, String name[, String attrName, String attrValue[, node base]]); number getNodeCount(String location[, node base]); node getNodeWidthIndex(String location, number index[, node base]); // 読み込み、保存 void load(String filename); void save(String filename[, String encoding]); } ※ 記述を単純化するため、型 IXMLDOMNode (または IXMLDOMElement) を単に node と記述している。 6. クラス詳細 クラス(もどき)の各メソッドについて説明する。 EasyXml([String filename]) --------------- コンストラクタ インスタンスを生成し、内部的に MSXML オブジェクトを作成、初期化する。 void clear() ------------ 初期化 void setRoot(String text) text ルート要素のタグ名 String getRoot() ------------------ ルート要素の設定または取得 ルート要素は1回だけ設定可能。 node findNode(String location[, node base]) location ノード位置 node 基点ノード ----------------------- 要素の取得 要素が存在しない場合には null を返す。 void setNode(String location[, node base]) location ノード位置 node 基点ノード node getNode(String location[, node base]) location ノード位置 node 基点ノード ---------------------- ノード取得または作成 要素を検索しそのノードを返す。 要素が存在しない場合、要素を新規に作成し、そのノードを返す。 ノードが作成できない場合、例外を発行する。 location で記述できるノード位置は タグ名を単純に '/' で連結したもの。 "a/bb/c[./@id='2']" のような属性付き XPath 式を記述することはできない。 setNode() と getNode() はどちらも同じ。 void setText(String location, String text[, node base]) location ノード位置 text テキスト node 基点ノード String getText(String location[, node base]) location ノード位置 node 基点ノード -------------------------- 指定ノード位置のテキストの設定または取得 テキストとはこれのこと。 テキスト void setAttribute(String location, String attrName, String attrValue[, node base]) location ノード位置 attrName 属性の名前 attrValue 属性の値 node 基点ノード String getAttribute(String location, String attrName[, node base]) location ノード位置 attrValue 属性の名前 node 基点ノード ------------------------------------------------ 指定ノード位置の属性の設定または取得 属性とはこれのこと。 node addNode(String parent, String name[, String attrName, String attrValue[, node base]]) parent 親ノード位置 name 追加ノード名 attrName 属性の名前 attrValue 属性の値 node 基点ノード ------------------------------------------------- 指定ノードに子ノードを追加 属性のみが異なる同名ノードを作成する場合に使用する。 ノード作成時に属性を設定することが可能。 number getNodeCount(String location[, node base]) location ノード位置 node 基点ノード ------------------------------------------------- ノード数の取得 指定したノード位置(path) に合致するノードの数を返す。 node getNodeWidthIndex(String location, number index[, node base]) location ノード位置 index インデックス node 基点ノード ------------------------------------------------- 指定インデックスのノード取得 指定したノード位置(path) に合致するノードが複数あるとき、 指定したインデックスのノードを取得する。 void load(String filename) filename ファイル名 ------------------- XML ファイル読み込み void save(String filename[, String encoding]) filename ファイル名 encoding エンコーディング (default: UTF-8) ------------------- XML ファイル書き込み 7. サンプルの実行方法 コマンドプロンプトでファイルを解凍したフォルダに移動後、 以下を入力する。 > cscript test.wsf 8. サポートされない機能 このライブラリは細かな操作を行うことを想定しないため、機能は DOM など比べてか なり制限される。 例えば位置指定の挿入や要素の削除などの基本的な機能もサポートしない。 これは簡単な定義ファイルの入出力用途で使用する場合、一括読み込みと一括書き込み が多く、編集操作の要件は低いと判断したためである。 もし編集操作を必要とした場合、その部分だけ MSXML をそのまま使うか、または、自 分でメソッドを追加すればよい。 このライブラリでは XML 操作機能の抜粋版を作成するのが目的であって機能および速 度を追求しない。 9. 使用条件 ご自由にどうぞ。 本プログラムおよびソースコードは無保証です。 本プログラムおよびソースコードの使用において生じた如何なる損害についても作者 は一切の責任を負いません。 10. 修正履歴 2004.07.25 新規作成 2004.12.05 メソッド整理、ドキュメント作成 2004.12.06 不具合修正 2005.04.17 文字エンコードの指定をコンストラクタでなく、保存時のパラメタとする。 コンストラクタへのパラメタはファイル名に変更、要注意。 11. 連絡先 金子尚史(kanegon) e-mail: wbs01621@mail.wbs.ne.jp