QT4 CG Meeting 131 Minutes 2025-07-29

Meeting index / QT4CG.org / Dashboard / GH Issues / GH Pull Requests

Table of Contents

Draft Minutes

Summary of new and continuing actions [0/5]

  • [ ] QT4CG-082-02: DN to work with NW to come to agreement on the fn:ranks proposal
  • [ ] QT4CG-116-01: Add a specific error code for unsupported options on doc and doc-available
  • [ ] QT4CG-118-01: MK to make an incorrect type raise an error in #1906
  • [ ] QT4CG-127-01: NW to diagram the JTree representing arbitrary XDM content.
  • [ ] QT4CG-128-03: NW to compare the file: module against the equivalent XProc 3.1 steps
  • [ ] QT4CG-131-01: MK to add a non-schema aware result.
  • [ ] QT4CG-131-02: MK to expand on the $E := <e A="p q r"… example
  • [ ] QT4CG-131-03: MK to change “invert” to “transpose” in the matrix example.
  • [ ] QT4CG-131-04: JK to double check the use of &lt;&lt; in the grammar where &gt;&gt; might have been intended

1. Administrivia

1.1. Roll call [8/12]

Regrets: DB, BTW.

  • [ ] David J Birnbaum (DB)
  • [X] Reece Dunn (RD)
  • [X] Christian Grün (CG)
  • [X] Joel Kalvesmaki (JK) [:07-]
  • [X] Michael Kay (MK)
  • [X] Juri Leino (JLO)
  • [X] John Lumley (JWL)
  • [ ] Dimitre Novatchev (DN)
  • [X] Wendell Piez (WP)
  • [ ] Ed Porter (EP)
  • [ ] Bethan Tovey-Walsh (BTW)
  • [X] Norm Tovey-Walsh (NW) Scribe. Chair.

1.2. Accept the agenda

Proposal: Accept the agenda.

Accepted.

1.3. Approve minutes of the previous meeting

Proposal: Accept the minutes of the previous meeting.

Accepted.

1.4. Next meeting

(Apologies for the errors in the agenda.)

The CG will not meet on 5 August. The following meeting is scheduled for 12 August 2025.

WP gives regrets for 12 August.

(The CG will take a short recess in late August. We will not meet on 26 August, 2 September, or 9 September.)

1.5. Review of open action items [0/5]

(Items marked [X] are believed to have been closed via email before this agenda was posted.)

  • [ ] QT4CG-082-02: DN to work with NW to come to agreement on the fn:ranks proposal
  • [ ] QT4CG-116-01: Add a specific error code for unsupported options on doc and doc-available
  • [ ] QT4CG-118-01: MK to make an incorrect type raise an error in #1906
  • [ ] QT4CG-127-01: NW to diagram the JTree representing arbitrary XDM content.
  • [ ] QT4CG-128-03: NW to compare the file: module against the equivalent XProc 3.1 steps

1.6. Review of open pull requests and issues

This section summarizes all of the issues and pull requests that need to be resolved before we can finish. See Technical Agenda below for the focus of this meeting.

1.6.1. Blocked

The following PRs are open but have merge conflicts or comments which suggest they aren’t ready for action.

  • PR #2124: 573 Functions to Construct Trees
  • PR #2063: 1996 Lookups, KeySpecifier: Literal, ContextValueRef
  • PR #2019: 1776: XSLT template rules for maps and array
  • PR #1062: 150bis revised proposal for fn:ranks

1.6.2. Merge without discussion

The following PRs are editorial, small, or otherwise appeared to be uncontroversial when the agenda was prepared. The chairs propose that these can be merged without discussion. If you think discussion is necessary, please say so.

  • PR #2129: 2099 Rename fn:jnode and jnode-type
  • PR #2117: 2082 parse-html options
  • PR #2115: 2084 - document order of axis steps when context value is a sequence
  • PR #2114: 2087 Change adaptive serialization of JNodes
    • MK notes that he changed the adaptive serializer to use jnode(), but we changed the function to jtree(). But at the moment, leave it.
  • PR #2113: 2102 Make type labels in diagram consistent

Proposed: merge without discussion.

Accepted.

1.6.3. Close without action

It has been proposed that the following issues be closed without action. If you think discussion is necessary, please say so.

  • Issue #2086: Can the ¶value property of a JNode be (or contain) a JNode?
  • Issue #1978: Function `map:build` does not allow expressing the dependency of a value on its key. Some simple types of maps cannot be built.
  • Issue #1946: We need examples of a record with an entry that is a %method and invoking this method with the result it must produce
  • Issue #1514: Editorial: optional position argument in function signature for for-each and other HOF
  • Issue #1175: XPath: Optional parameters in the definition of an inline function
  • Issue #150: fn:ranks: Produce all ranks in applying a function on the items of a sequence

Proposed: close without further action.

NW: I suggest we leave #150 open and I’ll see if I can get in touch with DN.

1.6.4. Substantive PRs

The following substantive PRs were open when this agenda was prepared.

  • PR #2116: 2112 Refine/revise the rules for get() in node tests
  • PR #2119: 2080 allow let $($head, $tail)
  • PR #2120: 2007 Revised design for xsl:array
  • PR #2130: Proposed new operator keywords: precedes, follows
  • PR #2123: 2051: XSLT group by cluster
  • PR #2019: 1776: XSLT template rules for maps and array
  • PR #2071: 77c deep update

2. Technical agenda

2.1. PR #2116: 2112 Refine/revise the rules for get() in node tests

See PR #2116

We have a diff for this one…

MK reviews the XPath specification.

  • MK: I’ve defined get() to use an absent focus. The original choice of making the focus be the same as the parent expression might be counter intuitive. It appears on the right of a slash and that might lead people to think it was evaluated against each item.
    • … There’s no error if you select things that don’t exist.
  • MK: There was a fair bit of comment on the PR.
  • JWL: The example with two hashes, child:get(#body, #x:body) made me think it was a function.
    • … You’ve got something that looks like a function but it doesn’t parse the arguments like a function.
    • … We have something similar for elements and schemas, this is a place where a comma inside a bracket thing that looks like a function call isn’t an argument separator.
      • … I understand what it is, but …
  • MK: Would it be better to make it an ExprSingle?
  • JWL: I think so.
  • CG: I already asked some questions in the PR. I’m still a challenge for me to understand all the details. You just said you didn’t want the expression evaluated for each item on the left hand side, but that’s what you said the semantics were on my last comment.

Some discussion of the comment:

The expression in get() is an operand/subexpression of the AxisStep expression and follows the standard semantics of subexpressions - it is evaluated as part of the evaluation of the parent expression. The only qualification is that it is evaluated with a absent focus.

In a path expression E1/E2, the semantics say that E2 is evaluated once for each item in the result of E1, and that applies also to a get() expression within E2. Expressions with side-effects are of course a pain, but they're a pain everywhere, not just here.

  • MK: If E1 is a map, there’s only one item on the left hand side.
    • … If it returned a sequence of maps, you’d evaluate it once for each map.
    • … You don’t do what you’d do for a predicate which is evaluate it once for each item in a loop.
  • CG: You could use position() then.
  • MK: Yes.
(: <a1/> :)
<xml><a1/><a2/></xml> / child::get(node-name(doc('https://server/inc.xml', { 'stable': false() })/*))

(: <a1/>, <a2/> :)
(<a1/>, <a2/>) / self::get(node-name(doc('https://server/inc.xml', { 'stable': false() })/*))
  • MK: I think the expression is evaluated once for each expression in E1.
  • CG: So we’d get <a1/> for the first case.
    • … In the second example, you’d get two results.
  • CG: I still think it would be helpful to have an equivalent expression.
    • You could put it in a function to make the context absent and put it outside the predicate.
  • MK: I’ll try to add an equivalent expression.

We’ll review again after that change.

  • CG: I think it’s even more sophisticated when we use union steps, for example the expression I added to the issue.
$gnodes/descendant::(text() | get(EXPR))

$gnodes/(
  let $S := fn() { data(EXPR) }()
  return descendant::item()[
    . instance of text() or
    some($S, atomic-equal(?, if(. instance of node()) then node-name() else jnode-selector()))  
  ]
)

Some discussion of what this means/is it allowed.

  • MK: Ok, that also ought to just work, but … it ought to be possible just to promote the union. One would like to think so…
  • JLO: Regarding this example and the optimization proposed, if I make the union in a different place, isn’t then the order different?
  • MK: In both cases, the result should be document order. That’s what / does.
    • … Whatever you do to that expression, you should get a result in document order.

2.2. PR #2119: 2080 allow let $($head, $tail)

See PR #2119

  • MK: This implements CG’s suggestion that rather than introduce “…” functionality, we make it the default for sequences.
  • MK: This is separate text for XPath and XQuery, even though this particular prose is the same. It’s a bit of a nightmare editorially.

MK reviews the XPath version.

  • MK: It’s a dynamic error to go off the end of an array.
  • JWL: If the attribute isn’t validated against a schema, then the value is two strings.
  • MK: Right.

ACTION QT4CG-131-01: MK to add a non-schema aware result.

  • RD: Where you have a schema aware thing like this, if you had the binding sequence, $p, $q, $r, $x, $y, $z then that expression would bind each of the values?
  • MK: Yes. It is determined by when atomization occurs. So you’d have to do explicit atomization on the right to get the six values.
  • RD: Or add as xs:string*.
  • MK: Yes.
  • JLO: In my head, it felt like there was some connection between $a and A.
  • MK: It was similar but not the same, it was designed to create an association.

ACTION QT4CG-131-02: MK to expand on the $E := <e A="p q r"… example

Proposal: Merge this PR.

Accepted.

2.3. PR #2120: 2007 Revised design for xsl:array

See PR #2120

MK explains that this arose from the case study I did rewriting the transpiler to use JSON rather than XML.

  • MK: I made a number of usability observations during the course of that study. One was that the use of xsl:map and xsl:array got very verbose.
    • … I discovered that xsl:array was almost always followed by an xsl:for-each.
    • … So you had to do xsl:array, xsl:for-each, and then xsl:array-member.
    • … A design pattern that works better is the one from xsl:merge where you have two expressions at the top level, one to process the input sequence where each item gives you a member and another to compute the member.

MK reviews the updated XSLT specification.

  • MK: We now have a for-each attribute and a select attribute.
    • … If for-each is absent, then it behaves the same as it does today.
    • … When for-each is present, you evaluate it to give you a sequence, then you get one array member for each item. You get the value of that member by evaluating the select attribute.

MK reviews the examples.

  • MK: There are some things that are better done in other ways, that’s okay.
  • MK: Nested arrays work much better than they did before.
  • JWL: So array members disappear. Can you make a static array without doing it in XPath?
    • … Suppose you wanted an XML structure in a static array?
  • MK: If it’s a completely arbitrary static array, then I think you have to do it in XPath.
    • … The contents of an array is a sequence constructor not an array constructor, that’s the problem.
    • … I considered an alternative where the contents isn’t a sequence constructor, but that gets too complicated if there are other XSL instructions in there.
  • JWL: Is there any cause for something like this on xsl:map?
  • MK: I looked at that; xsl:map already exists in 3.0 so it would have to be compatible.
    • … But it didn’t seem to have the same problems when I looked at it.
  • JWL: Just keeping them similar would be nice.
  • MK: I found it didn’t add value.
  • RD: The nested array example is actually a matrix transpose; it’s not an array inversion.
  • MK: Does invert mean something different?

ACTION QT4CG-131-03: MK to change “invert” to “transpose” in the matrix example.

  • JWL: It certainly does for a matrix.
  • JK: I’m still unhappy with the design. I understand that there a lot of singleton values in JSON structures. In XSLT, I’m often dealing with sequences of sequences. I put those in XML structures, but for better performance, I put them in maps today. But I really want to get them into arrays where the arrays can express sequences of sequences. I want to build up XML like structures within my arrays. I’m not so much interested in singleton members.
    • … For example, in the sequence constructor, I want to do a for-each-group and group them into single arrays. There’s a workaround, but it highlights a lack of parity between xsl:map and xsl:array.
    • … We have constructors for three of the four JSON data structures.
    • … Can we make a clear break between what’s inside an array and the attributes?
    • … Whenever you have an xsl:for-each, there’s probably a way to do it with templates. I always want to use templates instead. I’d like there to be some kind of parity between what we’re doing with maps and what we’re doing with arrays.
  • MK: I think that suggests keeping an xsl:array-member instruction but making it needed so often.
  • JK: An implementation ought to be able to work around some of this in the background.
  • MK: It’s not an implementation problem, it’s a usability problem.
    • … I think what I need to do is take another look at it. I need to work through JK’s examples and see if we can satisfy a wider range of use cases.

We’ll come back to this again.

2.4. PR #2130: Proposed new operator keywords: precedes, follows

See PR #2130

JK introduces the PR.

  • JK: The observation I make is that >> and << aren’t well known and you have to escape them in XSLT. It seems pretty easy to let us use an alias.
    • … I’m proposing precedes and follows.
    • … MK proposed introducing is-not at the same time.

JK reviews the grammar changes.

ACTION QT4CG-131-04: JK to double check the use of &lt;&lt; in the grammar where &gt;&gt; might have been intended.

  • JK: The is-not is defined the same way as is with true/false the other way around.
  • JK: I changed one use of << into precedes.
  • MK: That example is using tilde syntax which is obsolete.
  • JWL: There are no complications with spaces?
  • MK: The only one is the one that we already have with a leading /.
  • JWL: The requirement for whitespace separation aren’t a problem.
  • MK: There are no new issues there.

Proposal: Merge this PR.

Accepted.

3. Any other business

None heard.

4. Adjourned