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 }?test

XPath

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 }? $property

XPath

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