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 作为参数和节点类型发送,要么我需要某种 eval 从 xs:string 传递到运行时有效代码

有什么帮助吗?

4

2 回答 2

1

您可以考虑 (a) 生成过滤器是硬编码的查询,或 (b) 使用特定于 XQuery 供应商的 eval() 函数,或 (c) 如果您选择 XQuery 引擎,则使用 XQuery 3.0 高阶函数支持他们呢。

于 2012-08-05T08:21:48.033 回答
0

由于这个想法,我最终做了以下事情如何在 XQUERY 1.0 FLOWR 中解决这个自动增量 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 回答