XML::XQLモジュール(日本語チョー訳)

by Hippo2000(1999/8/18)

XML::XQLモジュールなのです。XQLチュートリアルも見てください。

なおこのドキュメントではXML::XQLモジュール(xql.pm)にpod2htmlを実行して作成されたファイルをベースにして、編集を加えて日本語に訳そうとしたものです。わかりにくい部分は本物を見てください。(^^;;
といってもこの原本自体かなりあやしげな部分があったりします。
自分が不勉強なだけ? f(^_^;;;;

原本の著作権はEnno Derksen 氏がお持ちです(詳しくは作者の部分を見てください)。
Enno Derksenさんにはメールで了解をいただきました。

なお内容等が間違っていたら修正します。ご連絡ください。


目次


名前

XML::XQL - XQLでXMLツリー構造を問い合わせるためのPerlモジュール


概要

 use XML::XQL;
 use XML::XQL::DOM;
 $parser = new XML::DOM::Parser;
 $doc = $parser->parsefile ("file.xml");
 # ルート要素bookの下にあるタグ名がtitleの要素を全て返す
 $query = new XML::XQL::Query (Expr => "book/title");
 @result = $query->solve ($doc);
 # または(タイプするのを減らすため)
 @result = XML::XQL::solve ("book/title", $doc);

説明

XML::XQLモジュールは1998年9月XSLワーキング・グループによって提出されたXQL (XML Query Language) プロポーザルを実装しています。その仕様は以下のURLで見ることが出来ます: http://www.w3.org/TandS/QL/QL98/pp/xql.html。XQL文法に関連する内容の大半は、これと一緒に配布されているXML::XQL::Tutorialでも見ることが出来ます。XQLはXML-QLとは違うということに注意して下さい!

現在の実装はXML::DOMモジュールと一緒でないと動きません。しかし一旦、設計が安定し、大きなバグがなくなったところで、XML::Groveのように別の拡張となるでしょう。

XQLは拡張できるように設計されており、この実装ではそれを忠実に守っています。ユーザは独自の関数、メソッド、比較演算子、データ型を追加することが出来ます。XMLツリー構造に組み込むことは(XML::Groveのように)、とっても簡単です。

XQLモジュールを使うには以下の

  use XML::XQL;

または

  use XML::XQL::Strict;

を使います。

StrictモジュールはXQL仕様でのコアXQL機能だけを提供します。デフォルト(つまりXML::XQLを使うと)'XQL+'を取得します。それはいくつかの追加の機能を持っています。

違いについてはセクション XQL+での追加の機能をご覧下さい。

このモジュールはまだ開発中です。やらなければならないことについては、XQL.pmのTo-doリスト(訳者注:XQL.pmの先頭にあります)をご覧下さい。提案は大歓迎です、これらの実装の問題が早く解決するほど、より早くこのモジュールのすべてを私たちは使うことができるようになります。

バグを見つけたら、テストケースの形式で送信していただければ、私は大喜びです。一緒に配布されているファイル t/template.tをご覧下さい。

共有してもいいと思う、スバらしい比較演算子、関数、メソッド、XQLデータ型が書けたら、enno@att.comまで送信して下さい。そうしたら私はそれをこのモジュールに追加しようと思います。


XML::XQLグローバル関数

solve (QUERY_STRING, INPUT_LIST...)
 @result = XML::XQL::solve ("doc//book", $doc);

これは以下のもののショートカットを提供します:

 $query = new XML::XQL::Query (Expr => "doc//book");
 @result = $query->solve ($doc);
defineFunction (NAME, FUNCREF, ARGCOUNT [, ALLOWED_OUTSIDE [, CONST, [QUERY_ARG]]])
指定された名前(NAME)でXQL関数を定義します(グローバルなレベルで。つまり新しく作られたすべての問い合わせに対して)。ARGCOUNTパラメータは1つの数値か数値のリストへのリファレンスのどちらかを指定します。1つの数値は[ARGCOUNT, ARGCOUNT]に展開されます。リストには2つで組の数値が入り、それぞれの数値はその関数が許す引数の数を示します。-1という値は制限なしを示します。例えば[2, 5, 7, 9, 12, -1] は、この関数が2,3,4,5,7,8,9,12個そしてそれ以上の引数を持つことが出来ることを意味します。引数の数はXQL問い合わせ文字列を解析するときにチェックされます。

2番目の引数はPerl関数または無名サブルーチンへのリファレンスでなければなりません。例えば '\&my_func' または 'sub { ... コード ... }' など。

ALLOWED_OUTSIDE (デフォルトは0)が1に設定されたら、関数またはメソッドはノード問い合わせ(node queries)で、外側の副問い合わせでも使われることが出来ます。(QueryコンストラクタのNodeQueryパラメータをご覧下さい)

CONST (デフォルトは0)が1に設定されれば、関数は「定数(constant)」とみなされます。詳しくは定数関数の実行をご覧下さい。

QUERY_ARG (デフォルトは0)が-1でなければ、そのインデックスをもった引数は「問い合わせパラメータ」だと見なされます。もし問い合わせパラメータが副問い合わせで、複数の値を返すのであれば、関数を実行した結果リストには、その副問い合わせそれぞれの結果の値が入ります。例えば「length(book/author)」は、book/authorによって返されるすべてのauthor要素の文字列長を示す数値のリストを返します。

(関数ではなく)メソッドだけがビックリマーク(!)演算子の後ろに現れることが出来ることに注意して下さい。これはXQL問い合わせ文字列の解析のときにチェックされます。

参照: defineMethod

generateFunction (NAME, FUNCNAME, RETURN_TYPE [, ARGCOUNT [, ALLOWED_OUTSIDE [, CONST [, QUERY_ARG]]]])
FUNCNAMEという名前でPerl関数のためのXQL関数ラッパーを生成し、定義します。XQL問い合わせ式での関数名は、NAMEになります。戻り値の型はXQLデータ型あるいはXML::XQL::Primitive型から派生したクラスの1つでなければなりません。(データ型を追加するもご覧下さい)。ARGCOUNT、ALLOWED_OUTSIDE、CONST、QUERY_ARGの意味についてはdefineFunctionをご覧下さい。

関数値はPerl関数の実装に渡される前に、常にxql_toStringでPerl文字列に変換されます。関数の戻り値はRETURN_TYPEの型のオブジェクトあるいは、undefであれば空リスト[]にキャストされます。この関数はXQLの基本型名を展開するためにexpandTypeを使います。もしRETURN_TYPEが"*"であれば、undefでなければそのまま関数の結果を返します。undefであれば[]を返します。

defineMethod (NAME, FUNCREF, ARGCOUNT [, ALLOWED_OUTSIDE])
指定された名前NAMEでXQLメソッドを定義します。(グローバルレベルで、つまり新しく作られる問い合わせすべてに)。ARGCOUNTパラメータは1つの数値でも数値のリストへのリファレンスのどちらでも指定することが出来ます。1つの数値は[ARGCOUNT, ARGCOUNT]に展開されます。リストには2つで組の数値が入り、それぞれの数値はその関数が許す引数の数を示します。-1という値は制限なしを示します。例えば[2, 5, 7, 9, 12, -1] は、この関数が2,3,4,5,7,8,9,12個そしてそれ以上の引数を持つことが出来ることを意味します。引数の数はXQL問い合わせ文字列を解析するときにチェックされます。
2番目の引数はPerl関数または無名サブルーチンへのリファレンスでなければなりません。例えば '\&my_func' または 'sub { ... コード ... }' など。
ALLOWED_OUTSIDE (デフォルトは0)が1に設定されたら、関数またはメソッドはノード問い合わせ(node queries)で、外側の副問い合わせでも使われることが出来ます。(QueryコンストラクタのNodeQueryパラメータをご覧下さい)

(関数ではなく)メソッドだけがビックリマーク(!)演算子の後ろに現れることが出来ることに注意して下さい。これはXQL問い合わせ文字列の解析のときにチェックされます。

参照: defineFunction

defineComparisonOperators (NAME => FUNCREF [, NAME => FUNCREF]*)
XQL比較演算子をグローバルレベルに定義します。FUNCREFパラメータは、Perl関数または無名サブルーチンへのリファレンスでなければなりません。例えば '\&my_func' または 'sub { ... コード ... }' など。

例: 演算子$my_op$と$my_op2$を定義します。

 defineComparisonOperators ('my_op' => \&my_op,
                            'my_op2' => sub { ... コード ... });
defineElementValueConvertor (TAG_NAME, FUNCREF)
指定されたタグ名(TAG_NAME)をもった要素(Element)のvalue()呼び出しに、指定された関数を使うことを定義します。関数は2つのパラメータを受け取ります。2番目が要素ノード(Element node)のタグ名(TAG_NAME)、1番目が要素ノードそのものです。FUNCREFはPerl関数へのリファレンスでなければいけません。例えば '\&my_func' または 無名サブルーチン。

例: 'date-of-birth'という名前の全ての要素がXML::XQL::Dateオブジェクトを返すように定義します。

        defineElementValueConvertor ('date-of-birth', sub {
                my $elem = shift;
                # 常にノードへ2番目のパラメータとして渡します。これは
                # そのオブジェクトのための参照ノードで、
                # ドキュメントでの順序で値をソートする時に使われます。
                new XML::XQL::Date ($elem->xql_text, $elem); 
        });

これらのコンバータはグローバルレベルだけで定義することが出来ます。問い合わせ毎にはできません。コンバータの定義をはずすためには、単にundefのFUNCREFを渡します。

defineAttrValueConvertor (ELEM_TAG_NAME, ATTR_NAME, FUNCREF)
指定されたATTR_NAMEという名前を持ち、親の要素が指定されたELEM_TAG_NAMEである属性のためのvalue()呼び出し結果を定義を指定された関数を使って定義します。ELEM_TAG_NAME での"*"は親の要素のタグ名に関係なくマッチするようにします。関数は3つのパラメータを受け取ります。3番目は親要素のタグ名(たとえELEM_TAG_NAMEが"*"であったとしても)、2番目はATTR_NAME、そして1番目には属性(Attribute)ノードそのものです。FUNCREFはPerl関数へのリファレンスでなければいけません。例えば '\&my_func' または 'sub { ... code ... }'

これらのコンバータはグローバルレベルだけで定義することが出来ます。問い合わせ毎にはできません。コンバータの定義をはずすためには、単にundefのFUNCREFを渡します。

defineTokenQ (Q)
q//文字列区切り文字のためのトークンをグローバルなレベルで定義します。デフォルトの値はq、XML::XQL::Strictではundefです。undefという値にすると、この機能は利用できません。
defineTokenQQ (QQ)
qq//文字列区切り文字のためのトークンをグローバルなレベルで定義します。デフォルトの値はqq、XML::XQL::Strictではundefです。undefという値にすると、この機能は利用できません。
expandType (TYPE)
XQL基本型の型名を展開するために内部で使われます。例えば、"Number"を"XML::XQL::Number"に展開します。これは大文字、小文字を区別しないので、"number"も"NuMbEr"も両方とも正しく展開されます。
defineExpandedTypes (ALIAS, FULL_NAME [, ...])
引数の各ペア毎にクラス名FULL_NAMEをALIASと短くすることを許します。定義はexpandType()で使われます。(expandTypeは大文字・小文字を区別しないため、ALIASは常に内部で小文字に変換されます)
 
"date"へのALIASを書き換えると、date()関数によって返され得るオブジェクトの型にも影響を与えます。
setErrorContextDelimiters (START, END, BOLD_ON, BOLD_OFF)
問い合わせの評価の途中でのエラーメッセージを表示するときに使われる区切り文字を設定します。UNIXでのデフォルトの区切り文字は`tput smul` (下線をつける)と`tput rmal` (下線をはずす)。他のシステムでは(tputを持たない)では、区切り文字は">>"と"<<"です。

エラーメッセージを表示するときには、エラーを起こした式の一部が区切り文字で囲まれます。つまりUnixでは下線がつきます。

 
ある種の式の一部は重要なキーワード、例えば"$and$"は太文字(bold)区切り文字BOLD_ON(UNIXでは`tput bold`、他は"")とBOLD_OFF(デフォルト:UNIXでは(`tput rmul` . `tput smul`) 、他では""。詳細はXML::XQL::XQL.pmの$BoldOffをご覧下さい)で囲まれます。
isEmptyList (VAR)
もしVARが[]であれば1を、そうでなければ0を返します。ユーザが定義した関数で使うことが出来ます。

XML::XQL::Queryメソッド

以下の関数は問い合わせレベルでも使うことが出来ます。つまり、Queryオブジェクトに対して呼ばれたとき、これらはそのQueryにだけに影響を与え、他には影響を与えません。

 defineFunction, defineMethod, defineComparisonOperators, 
 defineTokenQ, defineTokenQQ

詳細については、XML::XQLグローバル関数 をご覧下さい。これらの機能を特定のQueryに対して定義する方法として、適切な値をXML::XQL::Queryコンストラクタに渡すという方法もあります。

solve (INPUT_LIST...)
solveはノードのリストを取ります。そのそれはドキュメントでの順序にならんでいると想定され、同じドキュメントに属していなければならなりません。 例:
 $query = new XML::XQL::Query (Expr => "doc//book");
 @result = $query->solve ($doc);
 @result2 = $query->solve ($node1, $node2, $node3);

XML::XQL::Queryコンストラクタ

使用例:

 $query = new XML::XQL::Query(
        Expr => "book/author",
        Func => [ myfunc => \&my_func,          # 2つの関数を定義
                  myfunc2 => \&my_func2 ],
        FuncArgCount => [ myfunc2 => [2, -1] ], # myfunc2は2またはそれ以上の引数をもつ
        AllowedOutSideSubquery => [ myfunc => 1 ],
        ConstFunc => [ myfunc2 => 1],
        CompareOper => [ mycmp => \&mycmp ],    # 比較演算子の定義
        q => "str");                            # 文字列の区切り文字としてstr//を使う
Expr => STRING
評価される問い合わせ式
NodeQuery => BOOLEAN
もし1に設定されると、その問い合わせは(デフォルトの)全問い合わせ(=Full Query)ではなくノード問い合わせ(=Node Query) となります。ノード問い合わせは、ノードを返すことだけが出きる問い合わせです。全問い合わせはノードの値の他、XML基本型、要素型名、名前空間URI、つなげられたテキストノード、ノート型名といったノードでない値も返すことが出来ます。ノード問い合わせはXSLマッチと選択のパターンにできるのに対して、全問い合わせは他のアプリケーションで使われるので、違いは重大です。2つの問い合わせの形式の違いは自明で、ノード問い合わせの文法に制限としてだけ存在します。ノード問い合わせはネストした全問い合わせを持つことはできることに注意して下さい。
Func => [ FUNCNAME => FUNCREF, ...]
1つまたは複数の関数を定義します。FUNCNAMEは問い合わせ式で使われる名前です。FUNCREFは\&my_funcのような関数リファレンスまたは無名サブルーチンのどちらかが指定できます。参照: defineFunction
Method => [ FUNCNAME => FUNCREF, ...]
1つまたは複数のメソッドを定義します。FUNCNAMEは問い合わせ式で使われる名前です。FUNCREFは\&my_funcのような関数リファレンスまたは無名サブルーチンのどちらかが指定できます。参照: defineMethod
FuncArgCount => [ FUNCNAME => ARGCOUNT, ...]
1つまたは複数の関数またはメソッドのための引数の数を定義します。FUNCNAME は問い合わせ式で使われる名前です。参照: defineFunction と defineMethod
AllowedOutsideSubquery => [ FUNCNAME => BOOLEAN, ...]
指定された関数またはメソッドが外側の副問い合わせに許されるかどうかを定義します。FUNCNAMEは問い合わせ式で使われる名前です。 参照: defineFunction と defineMethod
ConstFunc => [ FUNCNAME => BOOLEAN, ...]
その関数(メソッドではなく)が「定数」関数であるかを定義します。FUNCNAMEは問い合わせ式で使われる名前です。定数(constant)の定義については定数関数の実行 をご覧下さい。参照: defineFunction と defineMethod
CompareOper => [ OPERNAME => FUNCREF, ...]
指定されたOPERNAMEで比較演算子を定義します。例えば、OPERNAMEが"contains"であれば、問い合わせで"$contains$"を使うことが出来ます。参照: defineComparisonOperators
q => TOKEN
q// トークンを定義する。 参照: defineTokenQ
qq => TOKEN
qq//トークンを定義する。参照: defineTokenQQ
Error => FUNCREF
問い合わせ式を解析している間にエラーが発生したときに呼び出される関数を定義します。デフォルトの関数はSTDERRにエラーメッセージを表示します。
Debug => FLAGS
問い合わせ式を解析するYappパーサのためのデバッグレベルを設定します。デフォルト値は0(何も表示しない)です。最大値は0x17で、やたらたくさん表示します。各ビットの意味についてはParse::Yappのマニュアルページをご覧下さい。
予約されているハッシュキー
ユーザは独自の(キー、値)のペアをQueryコンストラクタに加えることが出来ます。キー'Tree'は内部的に使われることに注意して下さい。

XQL+での追加の機能

順序演算子 ';' と';;'
順序演算子 ';' (先行)と';;' (直前)はXQL仕様には入っていませんが、XQLの設計者の一人であるJonathan Robieの'The Design of XQL'には入っています。それは以下のURLで見ることが出来ます:http://www.texcel.no/whitepapers/xql-design.html 。これらの意味の説明についてはXQLチュートリアルもご覧下さい。
q// と qq// 文字列トークン
q//とqq//風の文字列トークンが許されています。q// はPerlのシングル・クォートのように評価され、qq//はPerlのダブル・クォートのように評価されます。デフォルトのXQL文字列はエスケープなどを許していないために、シングルとダブルの両方のクォートを文字列に定義することができなかったことに注意して下さい。もし'q'と'qq'がお好みでなければ、何かほかのものに再定義したり、undefにすることでまったく未定義したりすることができます。例えば:
 # グローバル・レベルで−('q'を(再)定義しない)すべての問い合わせで共有されます
 XML::XQL::defineTokenQ ('k');
 XML::XQL::defineTokenQQ (undef);
 # 問い合わせレベルで−この問い合わせにのみ定義されます
 $query = new XML::XQL::Query (Expr => "book/title", q => 'k', qq => undef);
 
ここからは、k//がq//が動いていたようにのように動き、qq// はまったく機能しません。
問い合わせ文字列にコメントを埋め込むことが出来ます
例えば:
 $queryExpr = "book/title          # このコメントは問い合わせ文字列の中にあります
               [. = 'Moby Dick']"; # このコメントは外です
オプションのドル区切り文字と大文字/小文字の違いがないXQLキーワード
以下のXQLキーワードは大文字、小文字の違いがなく、ドル記号区切り文字は省略することもできます: $and$, $or$, $not$, $union$, $intersect$, $to$, $any$, $all$, $eq$, $ne$, $lt$, $gt$, $ge$, $le$, $ieq$, $ine$, $ilt$, $igt$, $ige$, $ile$.

例えば: $AND$, $And$, $aNd$, and, And, aNd はすべて正しく $and$ に置き換えられます。

XQL+ 比較演算子は($match$, $no_match$, $isa$, $can$) はドル区切り文字が必要で、大文字・小文字が区別されることに注意して下さい。

比較演算子: $match$ または '=~'
例えば "book/title =~ '/(Moby|Dick)/']" は、"Moby"まはた"Dick"が入った全てのbook/titleを返します。マッチ式はクォートで囲まれ、Perlのための//またはm//区切り文字が入っていなければなりません。

マッチの対象となる値をキャストするときには、両方ともTextに変換されます。

比較演算子: $no_match$ または '!~'
例えば "book/title !~ '/(Moby|Dick)/']"は、"Moby"または"Dick"が入っていない全てののbook/titleを返します。マッチ式はクォートで囲まれ、Perlのための//またはm//区切り文字が入っていなければなりません。

マッチの対象となる値をキャストするときには、両方ともTextに変換されます。

比較演算子: $isa$
例えば、'//. $isa$ "XML::XQL::Date"' は、value()関数がXML::XQL::Dateオブジェクトを返す全ての要素を返します。(value関数はある要素、属性のために特定の型のオブジェクトを返すようにオーバーライドされることがあることに注意してください)。XQL基本型名を展開するためにexpandTypeを使います。
比較演算子: $can$
例えば、'//. $can$ "swim"' は、value()関数が(Perl)swim()メソッドを実装しているオブジェクトを返す全ての要素を返します。(value関数はある要素、属性のために特定の型のオブジェクトを返すようにオーバーライドされることがあることに注意してください)。
関数: once (QUERY)
例えば、'once(id("foo"))' はQUERY式を問い合わせ毎にたった1回だけ評価します。ある問い合わせの結果(上記の例のような)は、1つの問い合わせのなかでは常に同じ値を返します。once()を使うとQUERYの結果は、問い合わせ残りのためにキャッシュされます。

「定数」関数の実行は常にキャシュされることに注意して下さい。 定数関数の実行もご覧下さい。

関数: subst (QUERY, EXPR, EXPR [,MODIFIERS, [MODE]])
例えば、 'subst(book/title, "[M|m]oby", "Dick", "g")'は、全てのbook/title要素の中の"Moby"または"moby"を"Dick"にグローバルに("g") 置き換えます。 内部ででPerlの置換演算子s///を使っています。どの区切り文字が内部で使われているか気にする必要はありません。関数は置換が行われた全てのbook/titleを返します。デフォルトのMODIFIERS文字列は""(空)です。関数名は"s"に短縮することができます。
 
ほとんどのノード型では、文字列とにマッチさせるためvalue()を(xql_toStringによって)文字列に変換し、マッチしたときに新しい値を設定するためにxql_setValueを使います。XQL基本型(Boolean、Number、Text)そして他の型(例えばDate)は、文字列をマッチするためにxql_toString使い、結果を設定するためにxql_setValueを使います。

元のXQL問い合わせ式で見つかった基本型に置換を行うと、定数の値を変更するということに注意して下さい。

MODEが0(デフォルト)であれば、要素ノード(Element node)のテキストブロック(text block)をマッチしたり、置換したりすることによって、要素ノードを違って取り扱います。テキストブロックは、配下のテキスト(Text)、CDATASection、EntityReferenceノードの生のテキストをつなげたものとして定義されます。このモードでは埋め込まれた要素ノードはとばされます。テキストブロックがマッチすると、元のノード型に関係なく、1つのテキストノードに置き換えられます。

MODEが1ならば、要素ノード(Element node)を他のノードと同じように扱います。つまり、value()を文字列に変換したりします。value()のデフォルトの実装がtext()を呼び出すことに注意して下さい。それは空白を正規化し、埋め込まれた子供の要素を(再帰的に)含みます。これは多分、ほとんどの場合、あなたがたが使いたいものとは違うでしょう。でも私はプロの霊能者じゃあないし...f(^_^)

関数:map (QUERY, CODE)
例えば、'map(book/title, "s/[M|m]oby/Dick/g; $_")'は、全てのbook/title要素の"Moby"あるいは"moby"を"Dick"にグローバル("g")置き換えます。内部ではPerlのmap演算子が使われます。関数は変更が行われた全てのbook/titleを返します。

??? とより多くの指定(=add more specifics )(※訳者注:どうなったんでしょう?)

関数: eval (EXPR [,TYPE])
Perl式EXPRを評価し指定されたTYPEの型のオブジェクトを返します。XQL基本型名を展開するためにexpandTypeを使います。もしevalの結果がundefであれば、空リスト[]が返されます。

例えば'eval("2 + 5", "Number")' は値7を持った数値(=Number)オブジェクトを返し、 'eval("%ENV{USER}")' は、ユーザ名を持った文字列(Text)オブジェクトを返します。

問い合わせの中で呼び出した、各呼び出しが同じ結果を返すとならば、戻り値をonce()を使ってキャッシュすることを考えてみて下さい。

??? とより多くの指定(=add more specifics )(※訳者注:どうなったんでしょう?)

関数: new (TYPE [, QUERY [, PAR] *])
指定されたTYPEの型のオブジェクトを新しく生成します。コンストラクタは引数をいくつでも持つことが出来ます。コンストラクタの最初の引数(new()関数の2番目の引数)は、「問い合わせパラメータ(=query parameter)」を見なされます。問い合わせパラメータ(=query parameter)の定義については、deineFunctionをご覧下さい。XQL基本型名を展開するためにexpandTypeを使います。
メソッド: :DOM_nodeType ()
DOMノード型を返します。これれはほとんどnodeType()と同じです。ただしCDATASectionとEntityReferenceノードは、DOM_nodeType()はそれぞれ4、5を返すのに対して、nodeType()はテキスト(Text)ノードであると見なして3を返します。
Perl組み込み関数のための関数ラッパー
XQL関数ラッパーは、ほとんどのPerl組み込み関数に対して提供されています。"substr"のようなPerl組み込み関数をXQL+問い合わせの中で使うとき、XQL関数ラッパーはその実行中に生成されます。これらの関数への引数は、問い合わせパラメータ(=query parameter)(定義についてはgenerateFunctionをご覧下さい)のための(1つまたは複数の値を返す)通常のXQL+副問い合わせかであるかもしれません。Perl組み込み関数のラッパーのほとんどは問い合わせパラメータのために引数0を持ちます。例外として:chmod(パラメータ1が問い合わせパラメータ)、chown(2),utime(2)。以下の関数は何も問い合わせパラメータを持ちません、これは全てのパラメータが1つの値でなければならないということを意味します:atan2, rand, srand, sprintf, rename, unlink, system。

関数の結果は適切なXQL基本型(数値(=Number)、テキスト(=Text)またはブール値(=Boolean))、または結果がundefであれば空リストににキャストされます。


実装の詳細

XQL組み込みデータ型
XQLエンジンは以下のオブジェクトクラスを内部的に使用します。数値、ブール値そしてテキストだけが基本的なXQL型と考えられます。
比較時の型のキャスト
XML比較(例えば$eq$)の中で2つの値が比較されるとき、まず同じデータ型にキャストされます。ノード値は最初にvalue()によって置き換えられます(つまりXQLvalue()関数が使われ、デフォルトではText値を返します。しかしもしユーザが選べばいかなるデータ型も返すことが出来ます)。結果の値はそして最も高いxql_primType()の値をもつオブジェクトの型にキャストされます。それは以下のようになります:ノード(=Node)(0)、テキスト(=Text )(1)、 数値(=Number) (2)、ブール値(=Boolean)(3)、日付(=Date)(4)、その他のデータ型(デフォルトでは4、しかしユーザによって書き換えられるかもしれません)

例えば、一方の値がテキスト(=Text)で、片方が数値(=Number)ならば、テキストの値は数値にキャストされ、($eq$だった場合)その結果、低レベル(Perl)の比較は以下のようになります:

 $number->xql_toString == $text->xql_toString

両方がテキスト値であれば、それは以下のようになります:

 $text1->xql_toString eq $text2->xql_toString

型キャストのところでは、XQL仕様はあいまいで矛盾してさえいます。この実装は、仕様の執筆者の一人である Joe Lapp との話し合いの結果を受けています。

データ型を追加する
独自のデータ を加えたいならば、XML::XQL::Primitiveから派生し、必要なメソッドを実装することを確認して下さい。

ここに説明をもっと加えるつもりです、しかし今のところはXQL基本型とDateクラス(Date.pmにある)のコードをご覧下さい。

ドキュメントでの順序
XQL仕様では問い合わせの結果は常にドキュメントでの順序で返されるといっています、これは元のXMLで現れる順序ということを意味します。ノードから取り出される値(例えばvalue()、text()、rawText()、nodeName()など)は、常に参照ノード(つまり値が取り出されるノード)へのポインタを持っています。(中間)結果リストが格納されるとき、これらのポインタは認識されます。現在のところ、結果リストが格納される湯iikつの場所は$union$式にあります。ここだけが結果リストが順序通りでないことができる唯一の場所です。(もしこれが本当でなければ、私に教えて下さい)
 
結びつけられた参照ノードを持たないノードでない値は、常に結果リストの最後に加えられた順序でつきます。XQL仕様はXML属性のための参照ノードは、それが属している要素だとしており、同じ参照ノードを持つ値の順序は不定だとしています。これは要素の順序と属性の順序は不定になるということを意味します。しかしXML::DOMモジュールが属性の順序をとらえることができるので、XQLエンジンは同じ事をします。そして、要素の属性はソートされ、ソートされた結果リストではそれらの親の要素の後に現れます。
定数関数の実行
もし"定数"の引数を与えたとき、関数がいつでも同じ値を返すならば、その関数は「定数(constant)」と見なされます。「定数」引数はXQL基本型(数値(Number)、ブール値(Boolean)、テキスト(Text))または"定数"関数実行のどちらかになるにすることができます。

例えば:

 date("12-03-1998")
 true()
 sin(0.3)
 length("abc")
 date(substr("12-03-1998 is the date", 0, 10))

は"定数"です、しかし以下のものは違います:

 length(book[2])

定数関数実行の結果はキャッシュされ、各問い合わせで一回だけ計算されます。 defineFunctinのCONSTパラメータもご覧下さい。once()呼び出しのなかで、定数関数実行をラップする必要はありません。

 
定数XQL関数には:date, true, falseそしてPerl組み込み関数のための多くのXQL+ラッパーがあります。ある組み込み関数ラッパーは、呼び出しで毎回評価されるように強制するためにコンスタントにされていません。例えば'mkdir("/user/enno/my_dir", "0644")'は複数回、呼ばれると違う結果を返すかもしれません。詳細についてはPlus.pmでの%PerlFuncをご覧下さい。
関数: count ([QUERY])
XQLの仕様ではcount() 関数はパラメータを持ちません。この実装ではQUERYパラメータが渡されたとき、QUERYの結果の数を返します。
メソッド: text ([RECURSE])
要素ノードを展開するとき、text()メソッドはサブ要素(sub-Elements)の展開されたtext()の値を加えます。RECURSEが0に設定されていると(デフォルトは1)、サブ要素を含みません。これは、例えば再帰的な内容での$match$演算子を使う(//演算子を使っての)ときに便利です。そのため子供の1つがマッチしたとき、親の要素は返しません。
メソッド: rawText ([RECURSE])
text()をご覧下さい。

参考資料

XQLの仕様 http://www.w3.org/TandS/QL/QL98/pp/xql.html

XQLの設計 http://www.texcel.no/whitepapers/xql-design.html

DOM レベル1の仕様 http://www.w3.org/TR/REC-DOM-Level-1

XMLの仕様 (Extensible Markup Language 1.0) at http://www.w3.org/TR/REC-xml

XML::Parser と XML::Parser::Expat マニュアル・ページ


作者

Please send bugs, comments and suggestions to Enno Derksen enno@att.com

バグ、コメント、提案は Enno Derksen enno@att.com に送って下さい。


ホーム Perlの小技

ご意見、ご質問はこちらの掲示板で受け付けています。
またメールは河馬屋(Nifty)にお願いします。