0

次の機能で成功したいのですが、ハードコーディングすると機能します。

declare function local:sort($collection as node()*, $filter as xs:SUBPATH?) as node()*{
     for $element in $collection
     order by 
        if ($filter) then ($element/$filter) (: OR SOME KIND OF fn:eval($filter) IF WE DEFINED $filter AS AN xs:string :)
        else              ($element/name()) (: Default :)
     descending
     return $element
};

そして、次のように呼び出すことができます。

for $element in local:sort(doc('data')/Data/*,'/@myAttr')
return $element

また

for $element in local:sort(doc('data')/Data/*,'/subnode/subnode/name()')
return $element

また

for $element in local:sort(doc('data')/Data/*,()) (: This is the default of function = own elment´s name :)
return $element

Mx の問題は、サブパスを渡すことです。相対 XPATH を引数およびノー​​ドのタイプとして送信する何らかの方法を知る必要があるか、または xs:string から実行時に有効なコードに渡すための何らかの eval が必要です。

何か助けはありますか?

4

2 に答える 2

1

(a) フィルターがハードコードされたクエリを生成する、(b) XQuery ベンダーに固有の eval() 関数を使用する、または (c) XQuery エンジンを選択した場合は XQuery 3.0 の高次関数を使用することを検討できます。まだそれらをサポートしています。

于 2012-08-05T08:21:48.033 に答える
0

XQUERY 1.0 FLOWRでこの autoincremental var ケースを解決するにはどうすればよいですか? :

(: This is a workaround solution as xquery:eval() is not working with var bindings until BaseX 7.3 version :)
(: It evals $context node + literal subpath with a pattern of '(/)lit/lit/lit/@attr' or '(/)lit/lit/lit' representing (/)lit/lit/lit/name(). If subpath null, it returns $context/name().:) 
declare function u:eval-path($context as node()*, $subnodes as xs:string*) as item()* {
  if(empty($subnodes)) then $context/name()
  else(
    if (count($subnodes) eq 1) then ( (: Last Element :)
               if (starts-with($subnodes[1],'@')) then $context/@*[name()=substring-after($subnodes[1],'@')]
                   else $context/*[name()=$subnodes[1]]/name()
         )   
    else if ($subnodes[1] eq '') then u:eval-path($context, $subnodes[position() gt 1])
    else u:eval-path($context/*[name()=$subnodes[1]],$subnodes[position() gt 1])
   )
};


(: Sorts the given collection by given criteria, which should be a pattern '(/)lit/lit/lit/@attr' or '(/)lit/lit/lit' representing (/)lit/lit/lit/name() :)
(: If criteria is null, everything is ordered by $elements/name(). Theres no way to filter intermediate nodes as in /lit/*[name()='X']/lit :)
declare function u:sort($collection as node()*, $criteria as xs:string?) as node()*{
    for $element in $collection
    order by u:eval-path($element,tokenize($criteria,'/'))
    ascending
    return $element
};
于 2012-08-05T20:09:40.253 に答える