This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.
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>
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.
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)
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
(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.