/catalog/bookEvery XPath expression is already valid XQuery
This surprises people the first time they see it. XQuery's grammar contains XPath's, so switching this Sandbox to XQuery mode does not require you to rewrite anything — a bare path is a complete query whose result is the selected nodes.
Example: /catalog/book
order bySorting — only XQuery can do it
Path expressions return nodes in document order, always. If the output has to be sorted by a value, that is a FLWOR job, and it is the single most common reason to switch a query from XPath to XQuery.
Example: for $b in //book order by $b/price return $b/title
group byGrouping and aggregation per key
XPath can count and sum a whole sequence, but it cannot produce one result per distinct key without awkward distinct-values() gymnastics. group by is built for exactly that shape. Note: the Sandbox's evaluation engine does not implement this clause yet, so queries using it will report a parse or 'not implemented' error here even though they are valid XQuery 3.1.
Example: for $b in //book group by $a := $b/author return count($b)
<row>{…}</row>Producing new XML rather than selecting nodes
XPath 3.1 can build maps and arrays, but it cannot build elements. If the deliverable is an XML document with a different shape from the input, you need XQuery's constructors.
Example: for $b in //book return <row>{$b/title}</row>
declare functionNamed, reusable, recursive logic
XPath 3.1 has inline anonymous functions, but no prolog and no way to name them for reuse across a query. Once a transformation needs recursion over a tree, XQuery is the practical choice.
Example: declare function local:slug($t) { lower-case($t) };
map { … }Shared ground — maps, arrays and the function library
Maps, arrays, the arrow operator, the simple map operator and the whole XPath 3.1 function library are available identically in both languages. When you only need those, staying in XPath keeps the query shorter and portable to more tools.
Example: map { 'title': $b/title, 'price': $b/price }