ligasgr / intellij-xquery

Plugin to support XQuery in Intellij Idea
Apache License 2.0
35 stars 23 forks source link

Support MarkLogic behavior that falls back to XPath function namespace where no function in scope has given signature #215

Open willsthompson opened 7 years ago

willsthompson commented 7 years ago

When no default function namespace is declared, MarkLogic automatically evaluates XQuery as if the XPath namespace were declared as default:

declare namespace fn = "http://www.w3.org/2005/xpath-functions";

I would assume most other XQuery implementations do this too, since it's suggested in the spec: https://www.w3.org/TR/xquery-30/#id-default-namespace

If no default function namespace declaration is present, the default function namespace is the namespace of XPath/XQuery functions, http://www.w3.org/2005/xpath-functions (however, an implementation may define a different default as specified in C.1 Static Context Components.)

ligasgr commented 7 years ago

Hi,

Please have a look on the MarkLogic documentation here.

Library Modules Default Function Namespace Defaults to Library Namespace

The default function namespace of an XQuery library module is the namespace of the library module. This allows you to declare functions in the library namespace without prefixing the functions. You can override the default function namespace with a declare default function namespace declaration in the prolog of the library module. For library modules where you do not override the default function namespace (and as a general best-practice), you should prefix the XQuery-standard functions (functions with the fn: prefix, which is bound to the http://www.w3.org/2005/xpath-functions namespace) with the fn: prefix. Note that main modules default function namespace defaults to the fn: namespace, which is different from library modules.

When you select MarkLogic as the Flavour in the settings this is how the system will treat it for module libraries. For all other Flavours and for MarkLogic main modules the system behaves as you've described. Please let me know if you've observed a different behaviour and provide examples!

willsthompson commented 7 years ago

That's interesting. The documentation is certainly clear, but that's not the behavior I see in ML v. 8.0-6.1 (and every previous version I've worked on). For example, a library module that makes several clearly meaningful XPath function calls:

xquery version "1.0-ml";
module namespace tn = "http://test/ML/default-namespace";

declare function tn:dostuff()
{
  string-join(
    for $i in tokenize('abc;123;jkl', ';')
    where true()
    return concat($i, '.')
  , ' ')
};

When imported into a main module, tn:dostuff() runs without error. Also interesting, even if you remove the tn prefix from tn:dostuff, it follows the behavior described in the documentation, associating it with the module namespace, while still resolving non-prefixed XPath functions to the XPath functions namespace.

But if an XPath function's local name is defined in the module namespace, any non-prefixed call to that function name will give priority to the module namespace over the XPath namespace:

declare function true()  (: Any call to true() instead of fn:true() will call this :)
{
  'foo' 
};
ligasgr commented 7 years ago

So the documentation is quite precise but leaves the last bit a bit 'undefined' where the implementation is actually quite strict.

It looks like if there is a local implementation in given module namespace then it goes to it. If there isn't it tries to fall-back to the default function namespace. Thanks for providing the examples and explanation!