xquerymarklogic

Load module with function having parameters via Marklogic query console


I’m trying to load an XQuery module with a simple function into the Modules database using the Marklogic query console.

xquery version "1.0-ml";

xdmp:document-insert("/my/app/my-module.xqy",
<module xmlns="http://marklogic.com/xdmp/module">
  xquery version "1.0-ml";
  module namespace my = "http://my.app/module";

  declare function my:hello-world($content as xs:string) {
    fn:concat("Hello from my module! ",$content)
  };
</module>

When I try and run the above I get the following error: [1.0-ml] XDMP-UNDVAR: (err:XPST0008) Undefined variable $content

I don’t know what I’m missing, $content is defined as a function parameter and the function seems to work outside of doing it as an install:

  xquery version "1.0-ml";
  declare namespace my = "http://my.app/module";

  declare function my:hello-world($content as xs:string) {
    fn:concat("Hello from my module! ",$content)
  };
  
  my:hello-world('test')

That works.

I can load a function that doesn't have a parameter without error:

xquery version "1.0-ml";

xdmp:document-insert("/my/app/my-module.xqy",
<module xmlns="http://marklogic.com/xdmp/module">
  xquery version "1.0-ml";
  module namespace my = "http://my.app/module";

  declare function my:hello-world() {
    fn:concat("Hello from my module!","Test")
  };
</module>)

I’m guessing its something basic that I’m miss understanding. Can someone help please?

Thank you

EDIT: Based on Chris's suggestion and some additional googling I removed the module tag and surrounded the module with the text{} wrapper:

xdmp:document-insert("/my/app/my-test.xqy",
text{
  'xquery version "1.0-ml";
  module namespace my = "http://my.app/module";

  declare function my:hello-world($content as xs:string) {
    fn:concat("Hello from my module! ",$content)
  };'
  },
  xdmp:default-permissions(),
  "http://my.app/module"
)

And it ran fine and allowed me to call it via:

import module namespace my="http://my.app/module" at "/my/app/my-test.xqy";
my:hello-world("TEST")

Solution

  • The braces ({ ... }) are directives in XQuery to evaluate their contents. If you look at what your working attempt actually stored, you will probably see that the fn:concat() function was evaluated. Similarly, in your first attempt, the reference to $content is being evaluated, but the declaration, outside the braces, is not evaluated and so is unavailable.

    You need to escape the braces by doubling them: {{ ... }}.

    I am not sure what you are doing with the <module> element, however. It’s not a construct I’ve ever seen, and I get an error trying to use an XQuery module that is not plain text. I recommend defining the module content as a string and inserting that.