SELECT and OUTPUT
Querying elements and shaping printed rows.
SELECT never modifies a document — it only prints.
SELECT GROUP
; print the whole group as-is
SELECT GROUP goods;
; without FOREACH, SELECT loops implicitly over the group's children
SELECT GROUP goods OUTPUT id, level;
; with FOREACH: filter and shape rows explicitly
SELECT GROUP goods
FOREACH good IN goods
WHERE good.cost > 500
OUTPUT good.id, good.cost, good.cost * 2 AS double_cost
;SELECT TAG / SELECT ROOT
SELECT TAG t prints every element with tag t, at any depth; SELECT ROOT drops the tag filter and prints every element in the document, any
tag — see Group vs. Tag vs. Root:
SELECT TAG ItemSpec; all ItemSpec elements, any depth
SELECT ROOT; every element in the document, any tagOUTPUT
OUTPUT is the emission point — like a SQL column list. It's evaluated
when execution reaches it, and prints a flat element containing only the
cited attributes/expressions:
OUTPUT *— the whole current element. This is the implicit default of aSELECTloop that has noOUTPUTat all.OUTPUT good.id, good.cost— only those attributes.OUTPUT good.cost * 2 AS double_cost— a computed expression needsASto name its output column; bare attribute references don't.- A missing attribute is silently omitted from the row (not printed as
empty) — contrast with
WHERE, where a missing attribute evaluates as false.
OUTPUT also works inside a plain FOREACH (not just SELECT loops), and
inside nested loops — where it joins scopes from multiple levels into one
flat row:
FOREACH office IN offices
FOREACH member IN office
WHERE member.cost > 5
OUTPUT office.id AS office, member.name, member.cost
;Here each printed row combines the outer office element with the inner
member element currently being visited.
Aggregate OUTPUT: COUNT, MIN, MAX, SUM, AVG
A regular OUTPUT prints one row per element the loop reaches. An
aggregate OUTPUT instead summarizes every reached element into a
single line of comma-joined plain numbers — no XML wrapper:
FOREACH v IN ItemSpec WHERE v.type = 0 OUTPUT COUNT(v.id);
; -> 2
FOREACH v IN ItemSpec WHERE v.type = 0
OUTPUT MIN(v.cost), MAX(v.cost), SUM(v.cost), AVG(v.cost)
;
; -> 10,30,40,20Rules:
COUNT(expr)counts elements whereexpris non-null;MIN/MAX/SUM/AVGignore elements whereexpris missing or non-numeric (same null-skipping spirit as everywhere else in the language).- Zero contributing elements reports
0for every function, not an error. - An aggregate
OUTPUTmust be the loop's onlyOUTPUT— mixing it with a plain attribute/expression, or with a secondOUTPUT, is a parse error, since there's no single row shape that could satisfy both a per-element projection and a whole-loop summary. - Aliases (
AS name) are accepted for readability but aren't printed — a single summary row has nothing to disambiguate. - Aggregate functions are only valid as a direct
OUTPUTitem, not insideWHEREor aSETexpression.
COUNT/MIN/MAX/SUM/AVG cover the common cases. Possible future
additions: FIRST/LAST (first/last matching value), CONCAT/
GROUP_CONCAT (join values with a separator), a distinct-values COUNT.