This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 30233 - [XSLT30] xsl:where-populated and interpretation of deemed-empty($item as item())
Summary: [XSLT30] xsl:where-populated and interpretation of deemed-empty($item as item())
Status: NEW
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XSLT 3.0 (show other bugs)
Version: Recommendation
Hardware: PC Windows NT
: P2 normal
Target Milestone: ---
Assignee: Michael Kay
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-03-21 16:14 UTC by Abel Braaksma
Modified: 2018-03-21 16:54 UTC (History)
0 users

See Also:


Attachments

Description Abel Braaksma 2018-03-21 16:14:40 UTC
Going over xsl:where-populated I found myself wondering what "deemed-empty($item as item())" means, in particular to "as item()", which I think isn't specified.

I don't precisely recall the discussions. But "as" could be interpreted as "cast as" (even though casting to item() is not possible). It is not clear to me whether then the empty sequence or a sequence of more-than-one should raise an error (I think not, but the way it is currently written, one may conclude a type error should be raised).

Perhaps we could add something like this (assuming this is what was intended):

* if the seqtor evaluates to an empty sequence, or a sequence of more-than-one items, the sequence is returned as-is

* if the seqtor evaluates to a sequence of exactly one item, the result of evaluating deemed-empty($item) defines its behavior

Alternatively, an error could be raised, but that would make the following invalid (apart from the code being senseless, but in practice it is not inconceivable that something like this happens in practice):

<xsl:where-populated>
  <a />
  <b />
</xsl:where-populated>
Comment 1 Michael Kay 2018-03-21 16:28:58 UTC
The phrase

where the function deemed-empty($item as item()) returns true if and only if $item is one of the following

is a slightly informal way of saying "where deemed-empty is a function that takes an item as input and returns a boolean, which is true if and only if the item is one of the following'.

The question of what deemed-empty does when given a non-singleton sequence doesn't arise because we never call it with anything other than a singleton item. Specifically, we only use it to evaluate the expression $R[not(deemed-empty(.))], where the argument is ".", which is always a singleton.
Comment 2 Michael Kay 2018-03-21 16:39:03 UTC
In fact the function could probably be expanded to:

<xsl:function name="deemed-empty" as="xs:boolean">
  <xsl:param name="item" as="item()"/>
  <xsl:sequence select="


     ($item instance of document-node() and not($item/child::node())

     or

     ($item instance of element() and not($item/child::node()) 

     or

     ($item instance of node() and (not($item instance of document-node()) and not($item instance of element()) and string-length($item) gt 0)

     or

     ($item instance of xs:anyAtomicType and string($item)="")

     or 

     ($item instance of map(*) and map:size($item) eq 0)

     or

     ($item instance of array(*) and every $x in array:flatten($item) satisfies deemed-empty($x))

     "/>
</xsl:function>

[except that "and" should have short-cut semantics for safety)
Comment 3 Abel Braaksma 2018-03-21 16:52:09 UTC
Oops, I think I misread the spec (again, sigh). 

The expression is "$R[not(deemed-empty(.))]" (where $R is the result of the seqtor). The function *signature* is "deemed-empty($item as item())", it is not meant as a function *call*.

Given that, most of my bug report is moot.

This means that:

<xsl:where-populated>
  <a />
  <b />
</xsl:where-populated>

would evaluate to the empty sequence, because neither <a /> nor </b> has children and each item is evaluated with the focus on deemed-empty.

and

<xsl:where-populated>
  <a />
  <b><x /></b>
</xsl:where-populated>

would evaluate to <b><x /></b>, removing <a /> from the result sequence.

Still, perhaps we can clarify this in a note, for instance to be a little clearer about the function signature. Proposal:

* change the text to read "...where the function deemed-empty has the signature deemed-empty($item as item()) as xs:boolean, which returns true if and only if $item is one of the following:"

* add a line that says explicitly that each item is evaluated in turn, but that for streamability, the normal rules apply, that is, there is no implicit fork applied
Comment 4 Abel Braaksma 2018-03-21 16:54:24 UTC
(looks like I was writing while you were writing the answer already, I think we were both arriving to the same conclusion)

Writing out the whole function is probably a good idea, it would make it clearer/more formal.