QT4
What's in it for me?
Declarative Amsterdam 2025
Juri Leino and John Lumley
- Overview of QT4CG activities
- Summaries of changed specs
- A late breaking change
Agenda
〰 BREAK 〰
- Continued sessions:
- XQuery
- XSLT
- Question and Answers
- Detailed sessions:
-
- XPath
- Functions and Operators
〰 BREAK 〰
- Started 6th September 2022
- 140 weekly (Zoom) meetings thus far
- ~12 active members
- >2000 issues and pull requests
- ~ 1 year to final feedback and completion
start
finish
QT4 Community Group
qt4cg.org — A Community Group under W3C
start
finish
- Started 6th September 2022
- 140 weekly (Zoom) meetings thus far
- ~12 active members
- >2000 issues and pull requests
- ~ 1 year to final feedback and completion
QT4 Community Group
qt4cg.org — A Community Group under W3C


QT4 Community Group
qt4cg.org — A Community Group under W3C
start
finish
- Started 6th September 2022
- 140 weekly (Zoom) meetings thus far
- ~12 active members
- >2000 issues and pull requests
- ~ 1 year to final feedback and completion


How to find changes?
Sections with significant changes in the TOC
New functions

Previous/ Next
Links to Issue and PR
How to find changes?
- Process (nested) maps and arrays as easily as node trees
- Full processing of (deep) JSON as a target Syntax and function additions to improve ease of use
- Minimal backwards incompatibility
Moving from 3.1 to 4.0
XPath
Functions + 0perators
XQuery
XSLT
XPath
XPath
-
Better support for nested maps/arrays
- JNode – an array/map entry with ‘axis-relationships’
- Deep lookup operators
- Maps are now ordered
- Structured Record (map) types
- Improved ‘pipelines’ => -> =!>
Functions and Operators
Functions and Operators
- mandatory higher-order functions
- EXPath File and Binary modules adopted and refined
- ~90 new functions
- ~60 functions extended
- consistency
- options records
XQuery
XQuery
- Declare custom records and enums
- Declare functions without prefix
- Use Qname literals in computed element constructors
- Optional function parameters
XSLT
XSLT
-
Syntactic additions to make stylesheets cleaner
- Enclosing modes
- Declared item/record types
- Better support for maps/arrays, including template matching
- Potential freezing of streaming support
A late breaking change...
Nodes
XNodes
XNodes
GNodes
GNodes
JNodes
XNodes
GTree
JTree
XTree
JNodes
-
parent: a reference to the parent JNode in the tree.
-
content: the value of the array member or map entry.
-
selector: the map key or array index that distinguishes this child from its siblings.
-
position: needed to handle "mixed" content
JNodes
jtree()
jnode-content()
jnode-selector()
jnode-position()
JNodes
[ "a", "b", "c"]
/*[1]
/..
/*[last()]
/string()JNodes
jtree([ "a", "b", "c"])
/*[1]
/..
/*[last()]
/string()JNodes
{ "fr": { "capital": "Paris", "languages": [ "French" ] }, "de": { "capital": "Berlin", "languages": [ "German" ] } } //languages
JNodes
{ "fr": { "capital": "Paris", "languages": [ "French" ] }, "de": { "capital": "Berlin", "languages": [ "German" ] } } //child::get("languages")
JNodes
{ "fr": { "capital": "Paris", "languages": [ "French" ] }, "de": { "capital": "Berlin", "languages": [ "German" ] } } //languages/jnode-content()
JNodes
XNodes
<node id="something">
content
</node>
{
'key': [1,2,3]
}〰 BREAK 〰
Fiddle
CODE
CONTEXT
RESULT
SELECT EXAMPLE
RUN
SELECT CONTEXT
TYPE
Fiddle
XPath
XPath
The map-Keyword
{ "this": "is", "a": "map" }map
XPath
The map-Keyword
{ "this": "is", "a": "map" }XPath
Lookups with ?
{ "test 1": 10 }?("test 1"){ 1: 10 }?1
{ "test": 10 }?testXPath
Lookups with ?
{ "test 1": 10 }?("test 1")XPath
Lookups with ?
{ "test 1": 10 }? "test 1"XPath
Lookups with ?
{ "test 1": 10 }?($property)XPath
Lookups with ?
{ "test 1": 10 }? $propertyXPath
Arrow operator
recap
EXPR => my:f() => my:g()
my:g(my:f(EXPR))
XPath
Arrow operator
recap
1 to 3 => sum() => math:pow(2) => function ($i) { ``[The square of the sum is `{$i}`]`` }()
XPath
1 to 3 => for-each(math:pow(?,2)) => sum() => function ($i) { ``[The sum of squares is `{$i}`]`` }()
Arrow operator
recap
XPath
ArrowBang
1 to 3
=!> math:pow(2)
=> sum()
=> function ($i) {
``[The sum of squares is `{$i}`]``
}()XPath
Arrow shortfalls
1 to 3 ! math:pow(2,.)
1 to 3
=!> fn($a){math:pow(2, $a)}()
function argument order
XPath
Arrow shortfalls
1 to 3 ! (. + 2)
1 to 3
=!> fn($a){ $a + 2 }()
RHS has to be a function call
XPath
Pipeline operator
3 -> math:pow(2, .)
EXPR -> EXPR
XPath
string templates
{ "number": 1, "name": "template" }
-> `This is {?number} string {?name}`not a string constructor
XPath
fn-Keyword
let $g := fn() {}
let $f := function () {}return ($f(), $g())
XPath
Focus Functions
let $id := fn{ . }
$id(1)
no arguments but the context value
XPath
Conditionals I
if (COND) { "COND was true" }
braced-if (without else)
XPath
Conditionals II
EXPR otherwise "fallback value"otherwise
XPath
type checks I
fn ($e as element()) {
(: do something with the element :)
}element wildcards
XPath
type checks I
fn ($e as element(*)) {
(: do something with the element :)
}element wildcards
XPath
type checks II
fn ($e as element(*:div)) {
(: work with all the divs :)
}element wildcards
XPath
type checks II
declare default namespace ##any; fn ($e as element(div)) { (: work with all the divs :) }
element wildcards
XPath
type checks III
//element(div|section)
(: select divs and sections :)
UnionNodeTests
XPath
type checks IV
fn ($input as (map(*)|array(*))) {
$input?1
}
ChoiceItemTypes
XPath
Destructuring I
let ($head, $tail) := (1 to 3) return ($tail, $head)
Destructuring a sequence
XPath
Destructuring I
let ($p, $q) := (1 to 3) return ($p, $q)
Destructuring a sequence
XPath
Destructuring II
let $m := { "yksi": 1, "kaksi": 2 }
let ${$yksi} := $m
return $yksi
Destructuring a map
XPath
Destructuring III
let $[$uno, $dos] := [ 23, 42 ] return $uno * $dos
Destructuring an array
XPath
Methods
$my:pool =?> area()
record =?> function(record, *)
$my:pool?area($my:pool)
Functions and Operators
〰 BREAK 〰
XQuery
Context I
- context item -> context value
- set context default value(s)
declare context value as document() external := document { (: the default :) }
Context II
declared namespaces: xs, fn, err
declare namespace array="???"; array:filter([1,-3,4,0], fn { math:abs(.) > 1 })
Context II
array:filter([1,-3,4,0], fn { math:abs(.) > 1 })
declared namespaces: xs, fn, err, map, array, math
Context II
declare option output:method "json";
array:filter([1,-3,4,0], fn {
math:abs(.) > 1
})declared namespaces: xs, fn, err, map, array, math, output
switch I
switch ($n) {
case "one" return xs:double(1)
case "two" return xs:double(2)
default return xs:double('NaN')
}
switch with curly braces
switch II
switch ($n) {
case "one", "un" return xs:double(1)
case "two" return xs:double(2)
default return xs:double("NaN")
}
multiple cases
Declare Custom Types
declare type my:binary as (xs:base64binary | xs:hexBinary);
enum
declare type my:color as enum(
"red", "green", "blue"
)Declare Custom Types
record
declare type my:rectangle as record(
height as xs:decimal,
width as xs:decimal
)Declare Custom Types
record
declare record my:rectangle (
height as xs:decimal,
width as xs:decimal
)Declare Custom Types
extendable record
declare record my:rectangle (
height as xs:decimal,
width as xs:decimal,
*
)Declare Custom Types
record with a method
declare record my:rectangle (
height as xs:decimal,
width as xs:decimal,
area as fn(my:rectangle) as xs:decimal := fn ($self) {
$self?height × $self?width
}
)Declare Custom Types
record with a method that is a focus function
declare record my:rectangle (
height as xs:decimal,
width as xs:decimal,
area as fn(my:rectangle) as xs:decimal := fn {
?height × ?width
}
)Declare Custom Types
try-catch with error map
try {
error(QName("local:error"),
"I can't let you do that, Dave.",
{ "custom": true() })
} catch * {
trace($err:map)
}Errors
{
'code': 'local:error',
'description': 'I can't let you do that, Dave.',
'value': { "custom": true() },
'lineNumber': 2,
'columnNumber': 4,
'module': 'my-module.xq',
'stacktrace': …,
⋮
}Errors
try-catch with finally
try {
let $i := 0 return 1 div $i
} catch * {
$err:description
} finally {
message(`1 div {$i}`) }
Finally
XSLT
〰 QUESTIONS 〰
DA25 QT4
By Juri Leino
DA25 QT4
- 28