@qt4cg statuses

This page displays recent status updates about the QT4CG project.

The are also captured in an RSS feed.

By year: 2026, 2025, 2024, 2023, 2022, 2021, 2020

QT4 CG meeting 181 draft minutes #minutes-09-22

22 Sep at 16:40:00 GMT

Draft minutes published.

Issue #2789 closed #closed-2789

22 Sep at 17:02:26 GMT

2787 XQuery changes to merge declare record and declare type

Issue #2909 closed #closed-2909

22 Sep at 16:32:04 GMT

Binary functions: Base64 URL en-/decoding

Issue #2910 closed #closed-2910

22 Sep at 16:32:03 GMT

2909 Binary functions: Base64 URL en-/decoding

Issue #1777 closed #closed-1777

22 Sep at 16:26:52 GMT

Shallow copy in XSLT with maps and arrays

Issue #2912 closed #closed-2912

22 Sep at 16:26:51 GMT

1777 Revise XSLT shallow copy for JNodes

Issue #2073 closed #closed-2073

22 Sep at 16:20:47 GMT

JNodes and Sequences

Issue #2878 closed #closed-2878

22 Sep at 16:20:45 GMT

2073 JNodes and Sequences

Issue #2861 closed #closed-2861

22 Sep at 16:17:20 GMT

Edge cases with CSV serialization

Issue #2862 closed #closed-2862

22 Sep at 16:17:19 GMT

2861 Clarify CSV serialization edge cases

Issue #2785 closed #closed-2785

22 Sep at 16:14:52 GMT

Make XSLT tunnel parameters available dynamically as a map

Issue #2925 created #created-2925

22 Sep at 16:08:23 GMT
`bin:to-base64url`, `bin:from-base64url`: other names?

https://github.com/qt4cg/qtspecs/pull/2910 was accepted today. We could discuss better names for the functions.

Issue #2924 created #created-2924

22 Sep at 06:13:42 GMT
NodeTest for JNodes

JNode node test discussion

We could also redefine the node test *, when applied to JNodes, so it only selects a JNode whose jvalue is a singleton map or array; to select other nodes, use the node test jnode(). That's a good analogy to the fact that with XNodes, * only selects elements.

Originally posted by @michaelhkay in #2922

Does that mean that foo selects only jnode(foo, (array(*)|map(*)|sequence(*)) ) (or sort of)?

In that case, we would need something like atom(bar) or @bar to select jnode(bar, *)[not(child::jnode(*))][not(self:(array(*)|map(*)) )].

That probably makes sense.

There is a differences here compared to XML. In XML, typically, most child nodes that have a name are elements, whereas most child nodes that are not elements are nameless. However, in map/array structures, most atomic nodes have a name, as well as not atomic nodes.

QT4 CG meeting 181 draft agenda #agenda-09-22

21 Sep at 11:00:00 GMT

Draft agenda published.

Issue #2923 created #created-2923

21 Sep at 10:11:31 GMT
Idempotent Coercion

We already discovered that coercing a function F to a required type T may be necessary even if F is already an instance of T, because the coerced function performs stronger checks on the types of the arguments supplied (see issue #1020).

We now have a test case:

<test-case name="recordTypeDecl-050" covers-40="PR1874">
      <description>Record types: field order, subtyping and coercion</description>
      <created by="Christian Gruen" on="2026-09-16"/>
      <test><![CDATA[
         declare record local:AB(a as xs:integer, b as xs:integer);
         declare record local:BA(b as xs:integer, a as xs:integer);
         declare function local:f($r as local:BA) { map:keys($r) };
         local:f(local:AB(1, 2))
      ]]></test>
      <result>
         <assert-deep-eq>"b", "a"</assert-deep-eq>
      </result>
   </test-case>

which demonstrates that coercing a record R to type T may be necessary even if R is already an instance of T, because it changes the order of entries in the record (the instance of check does not require fields to be in the right order).

This feels very counter-intuitive to me. On an ordinary English-language usage, "coercion" means modifying something to meet a given requirement, and shouldn't be necessary if the requirement is already met. If the order of fields is important enough to justify re-ordering, then it should also be important enough for instance of to fail.

I would like to see if we can adopt a general principle that if a value V is an instance of a type T, then coercion of V to T should be idempotent. This principle is important to allow type checking to be performed statically.

(There's an argument that if a function expects a record of type R, then the implementation of the function body should be able to make assumptions about the order of fields, in order to enable more efficient access. But on that line of reasoning, "instance of" should be a stronger test, so that the same logic can be used (say) in a branch of a typeswitch).

This may involve looking again at coercion of function items, which I previously thought was the only exception to this rule.

Another way of solving the problem for function calls would be to change the "instance of" rules. For example, given the example from the current spec,

let $f as function(xs:integer) as item()* := function($x) { $x + 1 }
return $f(12.3)

we would need to change the definition of "instance of" so that function($x) { $x + 1 } is no longer an instance of function(xs:integer) as item()* (instead, it is merely coercible to that type). As far as I can tell, that simply means removing the "contravariance" provision on argument types (§3.3.2.6 rule 2(f)). It seems a reasonable change, because the supplied function doesn't do everything that the expected type requires - it doesn't reject non-integer arguments.

An alternative solution would be to revert to the 3.1 spec here: no coercion is performed in this case and the above query succeeds, returning 13.3.

Issue #2922 created #created-2922

18 Sep at 02:11:20 GMT
Representation of sequence of items as a sequence of JNodes

Some ideas for discussion.

In the approach where sequences are represented as adjacent JNodes with the same jkey, a single JNode cannot serve to group an arbitrary sequence of items. Therefore, xsl:array-member should likely return a single-member array (and the sequence of them are concatenated with array:join), much like xsl:map-entry returns a single-entry map (and a sequence of them are concatenated with map:merge).

Originally posted by @ruv in #2073

This approach was roughly described in my comments on 2025-12-04 and 2026-09-01.

Example:

<jnode kind='map' key='()' value='{ "d": (7, [ 8, (9,10) ], 11), "e": (12,13), "f":14 }'>
    <jnode kind='leaf' key='d' value='7'/>
    <jnode kind='array' key='d' value='[ 8, (9,10) ]'>
      <jnode kind='leaf' key='1' value='8'/>
      <jnode kind='leaf' key='2' value='9'/>
      <jnode kind='leaf' key='2' value='10'/>
    </jnode>
    <jnode kind='leaf' key='d' value='11'/>
    <jnode kind='leaf' key='e' value='12'/>
    <jnode kind='leaf' key='e' value='13'/>
    <jnode kind='leaf' key='f' value='14'/>
</jnode>

Some problems of this approach are:

  • when copy a JNode (by xsl:copy-of or xsl:copy), jkey should be erased if the parent type is jnode(*,array(.*)), but we still have to separate new jnodes per array members.
  • it is unclear how to handle jkey conflicts when constructing jnode(*,map(.*)).
  • selecting the next JNode withing the same array-member (or map-entry) without knowing the jkey is too verbose.

To address these problems, a peer binary relation (a partial order) can be introduced in addition to the sibling relation. The peer relation should be preserved when JNodes are copied. Only JNodes that wrap items from the same sequence (e.g., from the same array-member) stand in the peer relationship to each other. Perhaps, it may be advisable to disjoin the peer and the sibling relations (that is, two JNodes cannot be in both peer and sibling relations at the same time).

The corresponding axes: preceding-peer::, following-peer::

/e[1] => jvalue() returns 12 /e[1]/following-peer::*[1] => jvalue() returns 13 /e[1]/following-sibling::*[1] => jvalue() returns 14 /d[last()] => jvalue() returns 11 /d[last()]/following-sibling::* => count() returns 3 /*[not(preceding-peer::*)] returns /( d[1] | e[1] | f[1] ) /*[not(following-peer::*)]/jvalue() returns (11, 13, 14)

To construct an array from a sequence $s of JNodes:

  <xsl:array>
    <xsl:for-each-group select="$s" group-start-with="*[ not(preceding-peer::*) ]">
      <xsl:array-member select="current-group()/jvalue()"/>
    </xsl:for-each>
  </xsl:array>

Probably, it should be an error if peer JNodes in $s are not transitively adjacent.

If two nodes are not peers and have the same jkey, this is only case requiring duplicate keys handling.


Update: to make the "peer" relation useful for XNodes too, the "sibling" relation should not change (i.e., it should not be disjoint from "peer").

Issue #2921 created #created-2921

17 Sep at 20:43:59 GMT
Lax record coercions

We’ve decided that…

let $coord as record(x, y) := { 'x': 1, 'y': 2, 'z': 3 }
return $coord

…raises an error. We could redesignate the deprecated extensibility syntax and use…

(: yields { 'x': 1, 'y': 2 } :)
let $coord as record(x, y, *) := { 'x': 1, 'y': 2, 'z': 3 }
return $coord

…to create a record with two entries that discards the remaining ones.

Pull request #2920 created #created-2920

16 Sep at 22:12:51 GMT
2813 clarifications for xsl:result-document

The primary purpose of this PR is to clarify the situation when an xsl:result-document instruction has an empty or absent href attribute, and thus writes to the principal output destination.

However, it also takes the opportunity to add many more clarifications to the serialization part of the XSLT spec, to improve the order of presentation, and to remove some redundancy

Fix #2813

Issue #2919 created #created-2919

16 Sep at 12:45:05 GMT
XQFO: feature requests from users

Some requests of “early adopters” (not sure whether that’s still the right term ;·), for functions that would be simple to add or modify:

1. fn:trim

Many functions come with a function for removing leading and trailing whitespace. It would be an easy-to-read shortcut for replace($line, '^\s+|\s+$'), i.e. for users who are not into regex.

2. fn:index-of-substring($string, $substring, $start?)

An alternatives for strings would simplify life (fn:index-of compares items, not strings).

3. fn:random-number-generator()?take(n)

Retrieving n random numbers is hard to achieve for non-experts. A shortcut would be desirable, for code like:

fold-left(1 to $n, random-number-generator(), fn { head(.) ! (?next(), ?number), tail(.) })
=> tail()

Pull request #2918 created #created-2918

16 Sep at 11:17:29 GMT
2600 Options on fn:collection()

Defines an options parameter for the fn:collection and fn:uri-collection functions.

Fix #2600 Fix #285

Issue #2917 created #created-2917

16 Sep at 08:18:35 GMT
Implementation-defined features

Some of the specifications have an appendix listing implementation-defined features. In some cases at least this is based on markup within the document text. In all cases, it has not been systematically reviewed or updated for changes in 4.0. We should either drop these appendixes or ensure they are accurate.

Pull request #2916 created #created-2916

15 Sep at 18:50:31 GMT
2915 `fn:current`: inline functions and `fn:function-lookup`

Closes #2915

Issue #2915 created #created-2915

15 Sep at 18:47:29 GMT
`fn:current`: inline functions and `fn:function-lookup`

The current spec says:

While the body of a function declaration or the initializing expression of a variable declaration is evaluated, it reverts to the context value of the query prolog.

It is unclear what current() returns in an inline function called from a default value. I think the current value should revert in every function body, just as the focus is absent in every function body.

The spec also lists the constructs that pass the caller’s context value to a default:

a static function call, a named function reference, or a partial function application

We should add fn:function-lookup (it can also create a function item with an omitted argument).

Issue #1459 closed #closed-1459

15 Sep at 18:23:15 GMT

Function properties and arities

Issue #2886 closed #closed-2886

15 Sep at 18:23:14 GMT

1459 Function properties and arities

Issue #2901 closed #closed-2901

15 Sep at 18:19:35 GMT

element-to-map: errors in the conversion plan

Issue #2903 closed #closed-2903

15 Sep at 18:19:34 GMT

2901 element-to-map: errors in the conversion plan

Issue #2906 closed #closed-2906

15 Sep at 18:19:02 GMT

Alternative for `+:=`: `put`?

Issue #2907 closed #closed-2907

15 Sep at 18:19:01 GMT

2906 Alternative for +:=: put

Issue #2883 closed #closed-2883

15 Sep at 17:53:52 GMT

parse-xml: strip-space=conditional

See 6055 more statuses in yearly archives.