by 川合孝典 Hippo2000(1999/9/1,9/2)
XML::XQLはPerlでXMLを検索するためのモジュールです。
これを使うさいの注意事項と単純な検索プログラムについて説明したいと思います。
更新履歴
1999/ 9/ 1 : 初回リリース
1999/ 9/ 2 :tkxql.plに整形する機能を追加
XML::XQLモジュールは1998年9月XSLワーキング・グループによって提出されたXQL (XML Query Language) プロポーザルを実装しています。その仕様は以下のURLで見ることが出来ます: http://www.w3.org/TandS/QL/QL98/pp/xql.html。XQL文法の説明が、一緒に配布されているTutorialにも入っています。
なおXML::XQLでは、XQL+ということで独自の拡張も追加しています。詳細についてはドキュメントをご覧下さい。
XML::XQLを利用するためには、以下のモジュールが必要になります。
| パッケージ名 | 説 明 |
|---|---|
| XML-DOM | XQLモジュールはDOMをベースにしています。 |
| Date-Manip | 日付を解釈するために利用されています。 |
| Parse-Yapp | 問い合わせ式の解析に使われます。 |
| XML-XQL | XML-XQLです。 |
なおXML::XQLは、PPMの標準のURLには、まだ用意されていないようです。
http://www.fastnetltd.ndirect.co.uk/Perl/zips/
にも固められたものがあるのですが、ちょっと古いものです。
http://pm.bi.umist.ac.uk/packages/ または http://www.bi.umist.ac.uk/packages/ にあるものが最新のものになっています。
Windowsで利用するXMLファイルのencodingの値には「Shift_JIS」、UNIXでは「euc-jp」が使われることが多いかと思います。
しかし、現在のところXML::Parserではこれらを認識しません。指定する場合には「x-sjis-unicode」あるいは「x-euc-unicode」をご利用下さい。詳しい説明がPerlをインストールしたディレクトリの下のsite\lib\xml\parser\encodingディレクトリ(通常はc:\perl\site\lib\xml\parser\encodings)にあるReadMeとJapanese_Encodings.msgというファイルをご覧下さい。
何の対策もなしにWindows上で起動すると「プログラム名またはファイルが違います」といったメッセージを5回出します。これはXML::XQLでは、問い合わせの評価の途中でのエラーメッセージを表示する時の区切り文字のために`tput smul` (下線をつける)と`tput rmal` (下線をはずす)、`tput bold`(太字にする)、`tput rmul` . `tput smul`(元に戻す)を使用しているためです。UNIXでは存在するtputというプログラムがないためにエラーメッセージが表示されるのです。エラーメッセージが出ても、検索には影響ありません。
これを避けるためには、「tput.bat」のようにダミーのプログラムを用意したり、xql.pmでtputを呼び出している箇所をコメント化するなどの対応が必要になります。(コメント化すると初期起動の時間が短くなるというメリットもあります。もちろん危険が伴いますが)
XML::XQLもIEのXMLDOMもXMLを読み込んで、DOMツリーをメモリ上に展開します。そのためあまり大きなファイルを利用しようとすると異常終了することがあります。Windowsで利用する場合には、メモリはファイルサイズの約100倍くらいの空き容量が必要な印象を受けました。メモリ48MBの95マシンでも300K程度のファイルの検索はできています。
Perlの機能だけで作成したtkxql.pl、IEの機能だけで作成したiexsl.htm、IEの機能をPerlから利用しているiexsl.plの3つのプログラムについて説明します。プログラム自体とても簡単なものなので、説明もとってもシンプルです。
ここで説明しているプログラムはここから(xql_pg101.lzh)まとめてダウンロードすることができます。
XML::XQLモジュールによるXML検索プログラムにTkモジュールでGUIをつけました。Win95、98で動作を確認しています。
※tkxql.plに検索結果を整形する機能を追加しました。(99/9/2)

XML::XQLモジュールとそのためのモジュールの他に以下のものを利用しています。
| パッケージ名 | 説 明 |
|---|---|
| I18N::cvt | 岡部さんがお作りになったモジュールです。UTF8<->SJISのコード変換を行います。 http://www.geocities.co.jp/SiliconValley-PaloAlto/2514/ にあります。 |
| Tk | GUIのためのモジュールです。 |
IEを利用して、XSLの問い合わせを行うプログラムです。IE5.0が必要です。
IE5.0のXSL検索機能をPerlから利用しています。
XML::XQLモジュールとそのためのモジュールの他に以下のものを利用しています。
| パッケージ名 | 説 明 |
|---|---|
| Tk | GUIのためのモジュールです。 |
| Win32::OLE | OLE連携のためのモジュールです。 |
IE5.0の機能を利用しているので、この他にIE5.0がインストールされている必要があります。
XML検索するためのもう1つのモジュールXML::QLを使った例です。
以下のモジュールを利用しています。
| パッケージ名 | 説 明 |
|---|---|
| XML-QL | QLのためのモジュールです。 |
| I18N::cvt | 岡部さんがお作りになったモジュールです。UTF8<->SJISのコード変換を行います。 http://www.geocities.co.jp/SiliconValley-PaloAlto/2514/ にあります。 |
| Tk | GUIのためのモジュールです。 |
なおXML::QLは、PPMの標準のURLには、まだ用意されていないようです。
http://pm.bi.umist.ac.uk/packages/ または http://www.bi.umist.ac.uk/packages/ にあるものが最新のものになっています。
添付したXMLファイルで簡単な検索の例をあげてみます。
問い合わせ文字列の詳しい説明については、参考資料をご覧下さい。
一緒に配布されている「組織図.xml」(IE5の機能を利用しているプログラムでは「組織図_ie.xml」)というファイルを利用します。
内容は以下のような12人の会社の組織を表しています。
<?xml version="1.0" encoding="x-sjis-unicode" ?>
<!-- サンプルデータ for XML::XQL by Hippo2000 -->
<組織図>
<社員 肩書="社長" 社員番号="1"><名前>社長大二郎</名前></社員>
<組織 組織名="技術部">
<社員 肩書="部長" 社員番号="9"><名前>部長一郎</名前></社員>
<組織 組織名="1課">
<社員 社員番号="17" 肩書="課長" 生年月日="Mar 23rd 1964"><名前>課長一郎</名前></社員>
<社員 社員番号="25" 肩書="リーダー" 生年月日="Mar 9th 1970"><名前>平花子</名前></社員>
<社員 社員番号="23" 生年月日="03/11/1970"><名前>平一郎</名前></社員>
<社員 社員番号="29" 生年月日="6/27/1966"><名前>平三郎</名前></社員>
</組織>
<組織 組織名="2課">
<社員 肩書="課長" 社員番号="22"><名前>課長花子</名前></社員>
<社員 社員番号="18"><名前>平太郎</名前></社員>
<社員 社員番号="20"><名前>平四郎</名前></社員>
</組織>
<社員 社員番号="8" 肩書="専門技師"><名前>技術一筋</名前></社員>
</組織>
<組織 組織名="営業部">
<社員 肩書="部長" 社員番号="30"><名前>部長次郎</名前></社員>
<社員 肩書="担当課長" 社員番号="27"><名前>課長一人</名前></社員>
</組織>
</組織図>
|
問い合わせ文字列のパターンとその結果を表にすると以下のようになります。
特にXML::XQLのみと書いていないもの以外は、3つのプログラムとも同じ動きになります。
| 種類 | 問い合わせ文字列 |
検索結果 |
|---|---|---|
| 要素の検索 | 社員名の一覧を表示する: //社員/名前 |
===== No:1==== <名前>社長大二郎</名前> ===== No:2==== <名前>部長一郎</名前> ===== No:3==== <名前>課長一郎</名前> ===== No:4==== <名前>平花子</名前> ===== No:5==== <名前>平一郎</名前> ===== No:6==== <名前>平三郎</名前> ===== No:7==== <名前>課長花子</名前> ===== No:8==== <名前>平太郎</名前> ===== No:9==== <名前>平四郎</名前> ===== No:10==== <名前>技術一筋</名前> ===== No:11==== <名前>部長次郎</名前> ===== No:12==== <名前>課長一人</名前> |
| 属性の検索 | 肩書きを持っている人の一覧表示: //社員[@肩書]/名前 |
===== No:1==== <名前>社長大二郎</名前> ===== No:2==== <名前>部長一郎</名前> ===== No:3==== <名前>課長一郎</名前> ===== No:4==== <名前>平花子</名前> ===== No:5==== <名前>課長花子</名前> ===== No:6==== <名前>技術一筋</名前> ===== No:7==== <名前>部長次郎</名前> ===== No:8==== <名前>課長一人</名前> |
| フィルターを利用する (要素の値) |
名前が「平三郎」である社員: //社員[名前="平三郎"] |
===== No:1==== <社員 社員番号="29" 生年月日="6/27/1966"><名前>平三郎</名前></社員> |
| フィルターを利用する (属性の値) |
社員番号が10番までの社員: //社員[@社員番号 $le$ 10] |
===== No:1==== <社員 肩書="社長" 社員番号="1"><名前>社長大二郎</名前></社員> ===== No:2==== <社員 肩書="部長" 社員番号="9"><名前>部長一郎</名前></社員> ===== No:3==== <社員 社員番号="8" 肩書="専門技師"><名前>技術一筋</名前></社員> |
| 添字を使う | ある組織の責任者: ※各組織の先頭が責任者と考えます。 //組織/社員[0]/名前 |
===== No:1==== <名前>部長一郎</名前> ===== No:2==== <名前>課長一郎</名前> ===== No:3==== <名前>課長花子</名前> ===== No:4==== <名前>部長次郎</名前> |
| メソッドを使う |
ある組織の責任者の次の人: ※各組織の先頭が責任者と考えます。 //組織/社員[index() = 1] |
===== No:1==== <社員 社員番号="25" 肩書="リーダー" 生年月日="Mar 9th 1970"><名前>平花子</名前></社員> ===== No:2==== <社員 社員番号="18"><名前>平太郎</名前></社員> ===== No:3==== <社員 社員番号="8" 肩書="専門技師"><名前>技術一筋</名前></社員> ===== No:4==== <社員 肩書="担当課長" 社員番号="27"><名前>課長一人</名前></社員> |
| 関数を使う (XML::XQLのみ) |
技術部に所属する人数: count(//組織[@組織名="技術部"]//社員) |
===== No:1==== XML::XQL::Number [0]:9 [1]: |
| XML::XQL独自の型を 利用する (XML::XQLのみ) |
生年月日が1964年3月23日か、1966年6月27日の社員: //社員[date(@生年月日) = "03/23/1964" $or$ date(@生年月日) = "Jun 27th 1966"] |
===== No:1==== <社員 社員番号="17" 肩書="課長" 生年月日="Mar 23rd 1964"><名前>課長一郎</名前></社員> ===== No:2==== <社員 社員番号="29" 生年月日="6/27/1966"><名前>平三郎</名前></社員> |
現在、データベースといえばAccess、OracleなどといったRDBが主流だと思われます。
今回、ここでは簡単な検索のためのXMLとXQL(あるいはXSLのパターン)を説明させていただきましたが、結構使いやすいのではないかと感じているのですが、いかがでしょう?データの更新/作成も普通のエディタでできます。
もちろん本当のデータベースではありませんから、メモリに展開できる分しか扱えませんし、索引を利用していないので検索スピードにも限界があります。
しかし、ここで出しているような簡単なデータであってもRDBの形式で実現するどうすればよいのでしょうか?
「社員」テーブルと「組織」テーブルを用意して、結合のためのIDを用意して...。あまり簡単には思えません。
特に「階層」を表そうとするとそれだけで私は途方にくれてしまいます。
※RDBで柔軟に階層をアクセスできる方法をご存知のかたがいらっしゃったら教えていただきたいと思っています。<(__)>
さらにデータベースということでいえば、メモリにあるのかデータベースにあるのかを意識しないように使えればとても便利だろうとは思っています。オブジェクト・デザイン社のObjectStoreにPerl用インタフェースをつけてくれぃ。
ご意見、ご質問はこちらの掲示板で受け付けています。
またメールは河馬屋(Nifty)にお願いします。