擬似コードは次のようになります。
let $myNode as node() := $node
for $subpath in tokenize($path,'/')
$myNode := $myNode/*[name()=$subpath] (: Here is the invalid line :)
xQuery 3.0 にはこのための演算子があることを知っています。xQuery 1.0 を求めています。
XQuery 2.0はありませんが、バージョンに関係なくFLWOR式だけではやりたいことはできません。現在のノードのセットは反復間で更新する必要がありますが、これはFLWOR式の動作ではありません。
そうは言っても、やりたいことはXQuery 1.0の再帰関数で簡単に実現できます。
declare function local:path(
$context as node()*,
$steps as xs:string*
) as node()* {
if(empty($steps)) then $context
else local:path(
$context/*[name() = $steps[1]],
$steps[position() gt 1]
)
};
で呼び出すことができます local:path(document{ <x><y>foo</y><z/></x> }, tokenize("x/y", '/'))
。
XQuery 3.0では、新しいトップレベル関数がなくても、さらに簡単に実行できます。
fn:fold-left(
function($context, $step) {
$context/*[name() eq $step]
},
document{ <x><y>foo</y><z/></x> },
tokenize('x/y', '/')
)
関数fn:fold-left(..)は再帰を内部的に処理し、各ステップで設定されたコンテキストを変更する方法を指定するだけで済みます。