XQuery, the Server Language
by Kurt Cagle
|
Pages: 1, 2, 3
For instance, we can create the traditional "Hello, World!" application as a web service, as shown in Listing 1 (hello_world.xq).
let $user := request:get-parameter("user","World")
let $message := if ($user = "World") then
<p>Greetings! Please enter your name: <input type="text" name="user" value=""/><input type="submit" value="Go!"/></p>
else
<p>Hi, {$user}! Welcome to the Hello, World Example!</p>
let $page :=
<html>
<head>
<title>Hello, {$user}!</title>
</head>
<body>
<h1>Hello, {$user}!</h1>
<form method="get" action="hello_world.xq">
{$message}
</form>
</body>
</html>
return $page
Listing 1: Hello, World, rendered in eXist's XQuery language
The eXist engine runs this XQuery as a REST based service, invocable from the command line. For instance, the document above might be given as http://localhost:8080/exist/rest//db/home/services/xq/hello_world.xq.
where this particular file is actually stored within the database itself.
The (: :) characters serve as comment delimiters The let keyword indicates the declaration and definition of a variable, with assignment being made explicitly using the := notation (with the bare equal sign serving to act as a Boolean comparison operator). Where things get a little strange is in the notion of containment. A single XML node (with or without children) also carries with it its own sense of "blockness," so that expressions such as if/then/else require either static values (such as numbers or strings), single XML elements (with or without children) or sequences of nodes and values delimited by parentheses. Thus, in the $message declaration, both the then and the else clauses return single elements.
The bracket notation within elements and attributes serves the same
purpose as bracket notation within XSLT: it evaluates the XPath
expressions and returns the results in the appropriate context, though
unlike XSLT bracketed expressions can return elements or attributes,
not just strings (meaning that you have to be more careful when
writing bracketed XQuery that you're not attempting to test a string
vs. an element or attribute inadvertently. This can be seen in the
insertion of the $message element within the larger XHTML
template.
XQuery makes use of what has become known as FLWOR (flower) notation, where the term is an acronym for the five primary keywords of XQuery notation: For, Let, Where, Order by and Return. Typically all XQuery statements have at a minimum at least one for or let expression, and then has a final return statement indicating what gets passed back out of the overall filter. Similarly, assignment statements can contain secondary for/let/if/then/else expressions, with the return keyword indicating the returned value or expression to be passed back to the assigned variable. Thus, in Listing 1, the line:
return $ page
at the very end of the XQuery returns the element defined in the variable $page. In an open query like the one above, this final return is used by eXist to pass the information to the servlet's output, in essence writing the buffers and sending the contents to the client.
I've deliberately held off discussing the first line of listing 1. The expression
let $user := request:get-parameter("user","World")
assigns to the variable user the results of the
get-parameter() function in the request
namespace. Put another way, this looks at either the incoming query
string (if the HTML form in question used the GET method) or the post
name/value data (if the method was POST) for the
parameter user. If the parameter exists,
then use it, otherwise, use the parameter value
"World".
This call is a staple of just about any server language. The ability to pull parameters from user input was one of the first reasons for building server-side scripting languages, but this is an eXist feature, not an XQuery one. However, the benefits of this particular feature should be obvious: if you can access information from the client, modify your outgoing streams (something that can be accomplished with the corresponding response: namespace) and maintain session and authentication information, then you have all of the functions necessary for a server language.
One of the more important features of XPath 2, upon which XQuery is based, comes from the realization that extensions are inevitable. There will always be things that fall beyond the immediate scope of the language but that are important to you as the developer. For this reason, XPath 2 (and hence XQuery) includes very clear conventions for defining additional functionality to the language...a fact which implies that other XML database vendors may very well want to look at this functionality and see whether it enhances their own products.