One common XQuery-related question that frequently comes up for developers is why do XQuery and XSLT have more than one operator for each comparison? The table below shows that there are twelve rather than six comparison operators, half of which use letters (such as
eq) and half of which use symbols (such as
|Value Comparison||General Comparison|
|less than or equal to||
|greater than or equal to||
In the 1.0-ml version of XQuery, there’s no difference in behavior by default;
eq behaves the same as
=, etc. If you want to dig a little deeper, this is because of function mapping, which you have the ability to enable or disable; if you disable function mapping,
eq will not behave the same as
However, whereas they behave the same in 1.0-ml, they actually mean different things. The value comparison operators (
lt, etc.) are designed for comparing single values (i.e., sequences of one value each). The general comparison operators (
<, etc.) are designed for comparing sequences of more than one value.
In the standard 1.0 version of XQuery (which MarkLogic also supports), you’ll get an error if you try to use a value comparison operator to compare sequences of more than one value:
xquery version "1.0"; "foo" eq ("foo","bar")
Here’s the error that results:
The 1.0-ml implementation relaxes this restriction, hence the effectively identical behavior of
=, etc. In XQuery version 1.0, you’d instead need to use a general comparison operator (
"foo" = ("foo","bar")
Using the general comparison operator will return true in both versions 1.0 and 1.0-ml and the expression will return true if any of the items on the left compare successfully with any of the items on the right. This is sometimes called “existential quantification.” A longer, more explicit way to write this in XQuery would be to use a “some” expression:
some $item1 in "foo", $item2 in ("foo","bar") satisfies $item1 eq $item2
You may have a policy (and I think it’s generally a good one) of always writing your code in version 1.0-ml, so does it even matter that you know this difference?
I think so. Knowing the difference enables you to write code that is not only more interoperable, but more expressive of your intentions:
For example, if you know that
$var will contain at most one number, and you want to compare it with a literal number, it’s best to use the value comparison operator, such as
$var le 5
<= would imply that $var may contain more than one number. On the other hand, if $var suddenly has more than one value, you’d want to use <= instead (to avoid an error in version 1.0), if in fact that’s your intention (i.e. return true if any of $var are less than or equal to the given number):
(: Are any of the numbers in $var less than or equal to 5? :) $var <= 5
Bringing this to a more practical example, say you have a <person> element in your XML and you want to find the person named “Bill”:
//person[name eq "Bill"]
If you know that a <person> will only ever have one <name>, then the above code is safe. But if you’re using 1.0 and one of your <person> elements has more than one <name>, then this will throw an error. If you’d rather find the <person> element that has any child <name> with a value of “Bill”, then the = operator will work the way you want (in both versions 1.0 and 1.0-ml):
//person[name = "Bill"]
To conclude, I’ll add one historical note. Before XPath 2.0 (which is what XQuery uses), there were no value comparison operators;
lt, and the like, simply didn’t exist. You only had =, >, <, etc. in XSLT/XPath 1.0. With XPath 2.0, XSLT 2.0, and XQuery, you now have a choice.
Read more about Function Mapping in 1.0-ml to better understand why these operators behave the same way.
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