XQuery Reference

Engine Support & Limits

This Sandbox evaluates XQuery 3.1 with FontoXPath, a conformant browser engine that nevertheless leaves a few clauses unimplemented. This page lists exactly what fails and, where one exists, the rewrite that works — so a query that errors here can be fixed in one edit rather than abandoned. Everything listed as unsupported is still valid XQuery 3.1 and will run in a server-side processor such as BaseX or Saxon.

group by (not supported)

Parsed but not implemented — rewrite with `distinct-values()`

A query containing `group by` fails with a 'not implemented' style error from the engine, even though the syntax is legal. The portable rewrite loops over `distinct-values()` of the grouping key and re-selects each group's members inside the body — see **XQuery Recipes** for the worked version. The Sandbox recognises this error and offers the rewrite in one click.

Example: for $r in //recipe group by $c := $r/cuisine return <g k="{$c}">{count($r)}</g>

count $i (not supported)

Use `at $i` or `position()` instead

The `count` clause, which numbers tuples *after* sorting, is unimplemented. When you do not need sorted numbering, `at $i` on the `for` clause is a direct substitute. When you do, sort into a variable first — `let $sorted := (for $a in //album order by $a/title return $a)` — then loop over `$sorted` with `at $i`.

Example: for $r in //recipe order by $r/name count $i return concat($i, '. ', $r/name)

window clauses (not supported)

`for tumbling window` / `for sliding window` are unavailable

Windowing over a sequence is unimplemented. For fixed-size chunks, iterate over an index range with `to` and slice with `subsequence()`; for adjacent pairs, index into the sequence twice. Both rewrites are portable and usually clearer for small windows.

Example: for tumbling window $w in //recipe start at $s when true() only end at $e when $e - $s eq 1 return count($w)

updating expressions (not supported)

XQuery Update Facility is out of scope

`insert`, `delete`, `replace`, `rename` and `copy … modify … return` belong to the XQuery Update Facility, a separate specification that this engine does not implement. Build the changed document with constructors instead — a FLWOR that copies what it wants and emits new markup for what it changes.

Example: copy $c := //recipe[1] modify delete node $c/cuisine return $c

fn:doc / fn:collection (not supported)

No filesystem or network document access in the browser

`doc()`, `doc-available()` and `collection()` need a document store the browser cannot provide, so queries run against the document loaded in the Document pane. To work across two documents, paste them under a single wrapper root and select each with a path — the join recipes then work unchanged.

Example: doc('catalog.xml')//recipe/name

module imports (not supported)

One query, one main module

`import module` resolves against a module store that does not exist here, so library modules cannot be loaded. Declare your functions in the query's own prolog with the `local:` prefix instead — see **Prolog & Modules**. Everything else in the prolog, including namespace, variable and default-order declarations, works normally.

Example: import module namespace lib = 'http://example.com/lib'; lib:label(//recipe[1])

schema-aware typing (not supported)

No `import schema`, no validated typed data

This is a non-schema-aware processor, so `import schema`, `validate` expressions and element/attribute tests against schema types are unavailable, and all document content arrives untyped. Cast explicitly with `xs:integer(...)`, `xs:date(...)` or `castable as` whenever a comparison depends on a type.

Example: import schema namespace c = 'http://example.com/cookbook'; //schema-element(recipe)

practical size limits

What actually slows the browser down

There is no hard document-size cap, but past roughly 2 MB the Sandbox switches into a relaxed mode that stops re-evaluating on every keystroke — run with the keyboard shortcut instead of waiting for live preview. Descendant-heavy patterns like `//*//*` are the usual cause of a slow query on a large document; anchoring the path or narrowing with a predicate fixes most cases.

← Back to the XQuery reference