The new website for MarkLogic is Visit it.

Punctuation in XPath, part 1: dot (“.”)

Back to blog
5 minute read
Back to blog
5 minute read
Graph bubbles of an interconnected network

Posts in this series:
Punctuation in XPath, part 1: dot (“.”)
Punctuation in XPath, part 2: slash (“/”)
Punctuation in XPath, part 3: “@” and “..”
Punctuation in XPath, part 4: predicates (“[…]”)
Punctuation in XPath, part 5: “//”

When you write XQuery, a large subset of what you’re writing is actually XPath 2.0. In fact, XQuery 1.0 is formally defined as an extension to, or superset of, XPath 2.0.

In this series of blog posts, I’m going to talk about the “punctuation” of XPath—all the little marks and what they mean: dot (“.”), slash (“/”), slash-slash (“//”), at-sign (“@”), dot-dot (“..”), etc. Since XPath is the common sub-language of both XQuery and XSLT, everything in this series applies both to XQuery and XSLT.

The dot, or period, character (“.”) in XPath is called the “context item expression” because it refers to the context item. This could be a node (such as an element, attribute, or text node), or an atomic value (such as a string, number, or boolean). When it’s a node, it’s also called the context node. Try typing “.” at the top of your XQuery expression in Query Console. What happens?

This is what you should get: [1.0-ml] XDMP-CONTEXT: (err:XPDY0002) Expression depends on the context where none is defined:

resulting error from typing typing "." at the top of your XQuery expression in CQ

If we look up the part in parentheses (“XPDY0002”), we’ll see that this is the standard message you get when you try to access the context item when none is defined. That’s because the context item is not defined at the top level in XQuery.

When “.” doesn’t yield an error, it returns an item (node or atomic value). Interestingly, those are the only two possibilities: a sequence of one item, or an error. Dot (“.”) will never return an empty sequence, nor a sequence of more than one item.

In XQuery, by default, the context item (“.”) is undefined at the top level of expressions (and MarkLogic’s implementation does not override that default). However, it’s different in XSLT, which has the concept of a current node. The current node, when defined, is what determines the context item at the top level of expressions.

XSLT normally assumes the presence of a single source document (“source tree”), whose document node becomes the initial context node. So the normal case in XSLT is the opposite of XQuery: a context item is defined at the top level of expressions. Try running this stylesheet (by copying and pasting the following code into Query Console):

<xsl:stylesheet version="2.0" 

  <xsl:template match="/">
    <xsl:copy-of select="."/> 

The result is not an error in this case but instead the source document (<my-doc/>) is copied to the result. That’s because the current node is the source tree’s document node (which you can tell from the match=”/” part).

result in CQ from running previous style sheet-- result is not an error; but the source document (<my-doc/>) is copied to the result

So when else is “.” defined (besides at the top level of expressions in XSLT)? There are two cases:

  1. inside a predicate (using “[…]”)
  2. inside a path expression step (to the right of “/”)

We’ll look at predicates first. Run this expression in CQ:

(1 to 100)[. mod 2 eq 0]

The predicate filters the sequence to its left, yielding only those items for which the predicate expression “. mod 2 eq 0” returns true. In this case, it yields all the even numbers between 1 and 100 (2, 4, 6, 8, …). In each case, the “.” expression refers to the context item. It gets evaluated exactly 100 times— once for each of the items in the sequence (1 to 100). First, “.” returns 1, then 2, then 3, etc.

A predicate can also be applied to a sequence of nodes, or even a heterogeneous sequence of nodes and atomic values. Run this expression in CQ:

(<foo/>, 5, "a string",<bar>Hello</bar>)[string(.) eq "Hello"]

In this case, the predicate gets evaluated four times, and “.” refers respectively to <foo/>, 5, “a string”, and <bar>Hello</bar>. It filters out every item whose value when converted to a string does not equal “Hello”. Thus, the result contains just one item: <bar>Hello</bar>.

The context item is also defined whenever a “/” is used in an expression. Let’s say we want to take a sequence of nodes and get the value of each one, converted to an upper-case string. For the sake of convenience, let’s use a bit of XQuery to define a global variable, giving us a document to work with.

Start by entering this into CQ:

declare variable $doc :=   

A natural way to get what we want would be to use a “for” expression. Add this to the text box in CQ and execute the query:

for $msg in $doc/msg return upper-case($msg)

Sure enough, that gives us what we want:


But we could also just use a “/” along with the dot. Replace the “for” expression with the following and run the query again:


In this case, rather than explicitly binding a named variable ($msg), we implicitly bind the context item. “.” is evaluated once for each of the items in the sequence returned by $doc/msg. So, it’s evaluated twice (returning a <msg> element both times) and converted to an uppercase string using the fn:upper-case() function.

One peculiar aspect of the “/” operator is that it can only apply to node sequences. Whereas it’s fine if we write this:

for $msg in ("Hello","Good-bye") return upper-case($msg)

We unfortunately can’t write this:


One final bit of trivia around “.” is that in XPath 1.0 (and XSLT 1.0), “.” was just syntax sugar for self::node(). And that’s still what it means— at least when the context item is a node. But XPath 2.0 (and XQuery) introduced the ability to have sequences of values, not just nodes. So in XPath 2.0, “.” is no longer a shorthand for something else. It’s now a primitive of the language— the “context item expression.”

We’ll touch on this again in part 2 of this series on the “/” operator.

Share this article

Read More

Related Posts

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.


Poker Fun with XQuery

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.

All Blog Articles

Protecting passwords in ml-gradle projects

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 file if there are multiple MarkLogic users that you need to configure. Instead of storing these passwords in, you can retrieve them from a location where they’re encrypted using a Gradle credentials plugin.

All Blog Articles

Getting Started with Apache Nifi: Migrating from Relational to MarkLogic

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

All Blog Articles

Sign up for a Demo

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