That is the question.
Have you ever noticed that when people call built-in XQuery functions like string(), count(), and collection(), they sometimes prefix the function name with fn:
, and sometimes they don’t? Why? When is it necessary to include the fn
prefix, and when is it okay to leave it out? Or perhaps, you’ve noticed that sometimes MarkLogic complains when you leave it out, and sometimes it doesn’t? This blog post is an attempt to clear up any confusion around this, and to help you define your own policy or preference on this most important issue that affects us all.
The prefix fn
is special in XQuery because it’s pre-defined to correspond to the namespace URI for built-in XPath functions. The upshot is that the following line is implicit in every XQuery module you write (unless you override it):
This means that you can call functions like fn:string()
and fn:concat()
, because the fn
namespace is already defined for you. But if you leave off the prefix from a function call, then you are relying on the default function namespace, which is often the same as the fn
namespace, and so it often works. (Ay, there’s the rub.) Don’t worry, I’ll explain what I mean by “often.”
But first, it’s worth pointing out that things are a bit different in XSLT, where the prefix fn
does not have any special standing. If you want to write fn:collection()
in XSLT, you’d need to explicitly bind the fn
prefix in your stylesheet:
<xsl:stylesheet xmlns:fn="http://www.w3.org/2005/xpath-functions" ...>
Of course, nobody does that in practice, because collection()
works just fine, and in fact, always works fine without a prefix in XSLT. In other words, the XPath function namespace is always, not just often, the default function namespace in XSLT, and there’s no way to override it.
The difference in XQuery is that you can override the default function namespace, using a declaration like this:
declare default function namespace "http://example.com/my-function-ns";
If you don’t include a line like this in your code, then it’s up to your XQuery implementation to determine what the “default default” function namespace is. The XQuery spec “recommends” that implementations set that “default default” to the XPath function namespace (the “default default default”?), but it also allows them to override it. As it happens, MarkLogic is an implementation that overrides it…at least part of the time.
Okay, now I’ll explain what I mean by “often.” In XQuery, there are two kinds of modules: main modules and library modules. MarkLogic sets the default function namespace to the fn
namespace for main modules, but for library modules, the default function namespace is set to the module namespace. The nice thing about this is that, in library modules, you aren’t immediately forced to use a prefix on the functions that you define:
On the other hand, this means that you need to use the fn:
prefix on any calls you make to the built-in XPath functions. So a typical scenario is that collection()
works fine in your main module, but you have to write fn:collection()
in your library module. This may get annoying if you decide you want to re-use some of the code in your main module by moving it to a library module. In this case, cut-and-paste doesn’t cut it; you’ll have to add fn:
in a bunch of places. I think we can all agree that this is a sea of troubles worth taking arms against.
The question is: how you want to deal with it? I see two general approaches to avoiding the above pain:
fn:
prefix, ORfn
namespace as the default function namespace in library modules, so you never have to use the fn
prefix.Both methods are safe, so it largely comes down to personal preference. One thing to note about option 2 is that you’ll need to start using a prefix on your own module function definitions and function calls, something you have to do anyway when you’re calling them from elsewhere. If we really wanted to argue about it, I could give other reasons for one or the other (my personal preference is option 2), but I’ll leave that discussion to the comments — bring it on!
Before I leave you, I want to make sure you know how to accomplish option 2 and forever rid yourself of the need of remembering to type fn:
. Just put the following boilerplate in the prolog of each of your library modules:
Happy coding!
Like what you just read, here are a few more articles for you to check out or you can visit our blog overview page to see more.
In this post, we dive into building a full five-card draw poker game with a configurable number of players. Written in XQuery 1.0, along with MarkLogic extensions to the language, this game provides examples of some great programming capabilities, including usage of maps, recursions, random numbers, and side effects. Hopefully, we will show those new to XQuery a look at the language that they may not get to see in other tutorials or examples.
If you are getting involved in a project using ml-gradle, this tip should come in handy if you are not allowed to put passwords (especially the admin password!) in plain text. Without this restriction, you may have multiple passwords in your gradle.properties file if there are multiple MarkLogic users that you need to configure. Instead of storing these passwords in gradle.properties, you can retrieve them from a location where they’re encrypted using a Gradle credentials plugin.
Apache NiFi introduces a code-free approach of migrating content directly from a relational database system into MarkLogic. Here we walk you through getting started with migrating data from a relational database into MarkLogic
Don’t waste time stitching together components. MarkLogic combines the power of a multi-model database, search, and semantic AI technology in a single platform with mastering, metadata management, government-grade security and more.
Request a Demo