} element around the attribute node. Here is the output: \snippet snippets/code/doc_src_qtxmlpatterns.qdoc 28 The output contains one \c{
} element for each \c{xml:id} attribute in the cookbook. Note that XQuery puts each attribute in the right place in its \c{
} element, despite the fact that in the \e{return} clause, the \c{$i} variable is positioned as if it is meant to become \c{
} element content.
The other two examples from the \l{Wildcards in Name Tests} {wildcard}
section can be rewritten the same way. Here is the XQuery that selects
all the \c{name} attributes, regardless of namespace:
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 26
And here is its output:
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 29
And here is the XQuery that selects all the attributes from the
\e{document element}:
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 27
And here is its output:
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 30
\section2 Element Constructors are Expressions
Because node constructors are expressions, they can be used in
XQueries wherever expressions are allowed.
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 40
If \c{cookbook.xml} is loaded without error, a \c{ } nodes we create in the
output to be in the standard XHTML namespace, so we declare the
default namespace to be \c{http://www.w3.org/1999/xhtml}. That's
correct for the output, but that same default namespace will also be
applied to the node names in the path expression we're trying to match
in the input (\c{/tests/test[@status = "failure"]}), which is wrong,
because the namespace used in \c{testResult.xml} is perhaps in the
empty namespace. So we must declare that namespace too, with a
namespace prefix, and then use the prefix with the node names in
the path expression. This one will probably work better:
\quotefile snippets/patternist/embedDataInXHTML2.xq
\section2 Why doesn't my return clause work?
Recall that XQuery is an \e{expression-based} language, not
\e{statement-based}. Because an XQuery is a lot of expressions,
understanding XQuery expression precedence is very important.
Consider the following query:
\quotefile snippets/patternist/forClause2.xq
It looks ok, but it isn't. It is supposed to be a FLWOR expression
comprising a \e{for} clause and a \e{return} clause, but it isn't just
that. It \e{has} a FLWOR expression, certainly (with the \e{for} and
\e{return} clauses), but it \e{also} has an arithmetic expression
(\e{+ $d}) dangling at the end because we didn't enclose the return
expression in parentheses.
Using parentheses to establish precedence is more important in XQuery
than in other languages, because XQuery is \e{expression-based}. In
In this case, without parantheses enclosing \c{$i + $d}, the return
clause only returns \c{$i}. The \c{+$d} will have the result of the
FLWOR expression as its left operand. And, since the scope of variable
\c{$d} ends at the end of the \e{return} clause, a variable out of
scope error will be reported. Correct these problems by using
parentheses.
\quotefile snippets/patternist/forClause.xq
\section2 Why didn't my expression get evaluated?
You probably misplaced some curly braces. When you want an expression
evaluated inside an element constructor, enclose the expression in
curly braces. Without the curly braces, the expression will be
interpreted as text. Here is a \c{sum()} expression used in an \c{ }
element. Apply a position filter (\c{[1]}) to the \c{/span} path step:
\quotefile snippets/patternist/filterOnStep.xq
Applying the \c{[1]} filter to the \c{/span} step returns the first
\c{} element of each \c{ } element:
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 41
\note: You can write the same query this way:
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 44
Or you can reduce it right down to this:
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 45
On the other hand, suppose you really want only one \c{}
element, the first one in the document (i.e., you only want the first
\c{} element in the first \c{ } element). Then you have to do
more filtering. There are two ways you can do it. You can apply the
\c{[1]} filter in the same place as above but enclose the path
expression in parentheses:
\quotefile snippets/patternist/filterOnPath.xq
Or you can apply a second position filter (\c{[1]} again) to the
\c{/p} path step:
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 43
Either way the query will return only the first \c{} element in
the document:
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 42
\section2 Why doesn't my FLWOR behave as expected?
The quick answer is you probably expected your XQuery FLWOR to behave
just like a C++ \e{for} loop. But they aren't the same. Consider a
simple example:
\quotefile snippets/patternist/letOrderBy.xq
This query evaluates to \e{4 -4 -2 2 -8 8}. The \e{for} clause does
set up a \e{for} loop style iteration, which does evaluate the rest of
the FLWOR multiple times, one time for each value returned by the
\e{in} expression. That much is similar to the C++ \e{for} loop.
But consider the \e{return} clause. In C++ if you hit a \e{return}
statement, you break out of the \e{for} loop and return from the
function with one value. Not so in XQuery. The \e{return} clause is
the last clause of the FLWOR, and it means: \e{Append the return value
to the result list and then begin the next iteration of the FLWOR}.
When the \e{for} clause's \e{in} expression no longer returns a value,
the entire result list is returned.
Next, consider the \e{order by} clause. It doesn't do any sorting on
each iteration of the FLWOR. It just evaluates its expression on each
iteration (\c{$a} in this case) to get an ordering value to map to the
result item from each iteration. These ordering values are kept in a
parallel list. The result list is sorted at the end using the parallel
list of ordering values.
The last difference to note here is that the \e{let} clause does
\e{not} set up an iteration through a sequence of values like the
\e{for} clause does. The \e{let} clause isn't a sort of nested loop.
It isn't a loop at all. It is just a variable binding. On each
iteration, it binds the \e{entire} sequence of values on the right to
the variable on the left. In the example above, it binds (4 -4) to
\c{$b} on the first iteration, (-2 2) on the second iteration, and (-8
8) on the third iteration. So the following query doesn't iterate
through anything, and doesn't do any ordering:
\quotefile snippets/patternist/invalidLetOrderBy.xq
It binds the entire sequence (2, 3, 1) to \c{$i} one time only; the
\e{order by} clause only has one thing to order and hence does
nothing, and the query evaluates to 2 3 1, the sequence assigned to
\c{$i}.
\note We didn't include a \e{where} clause in the example. The
\e{where} clause is for filtering results.
\section2 Why are my elements created in the wrong order?
The short answer is your elements are \e{not} created in the wrong
order, because when appearing as operands to a path expression,
there is no correct order. Consider the following query,
which again uses the input file \c{doc.txt}:
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 46
The query finds all the \c{ } elements in the file. For each \c{ }
element, it builds a \c{ } element in the output containing the
concatenated contents of all the \c{ } element's child \c{}
elements. Running the query through \c{xmlpatterns} might produce the
following output, which is not sorted in the expected order.
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 47
You can use a \e{for} loop to ensure that the order of
the result set corresponds to the order of the input sequence:
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 48
This version produces the same result set but in the expected order:
\snippet snippets/code/doc_src_qtxmlpatterns.qdoc 49
\section2 Why can't I use \c{true} and \c{false} in my XQuery?
You can, but not by just using the names \c{true} and \c{false}
directly, because they are \l{Name Tests} {name tests} although they look
like boolean constants. The simple way to create the boolean values is
to use the builtin functions \c{true()} and \c{false()} wherever
you want to use \c{true} and \c{false}. The other way is to invoke the
boolean constructor:
\quotefile snippets/patternist/xsBooleanTrue.xq
*/