Re: [xsl] Numeric top-level predicates in patterns

Subject: Re: [xsl] Numeric top-level predicates in patterns
From: "Abel Braaksma (Exselt)" <abel@xxxxxxxxxx>
Date: Wed, 02 Apr 2014 19:05:46 +0200
On 2-4-2014 17:15, Michael Kay wrote:
>> The rules I am after is, in this order:
>> 1) numerical predicates lower than zero never select anything
> More precisely, the only numerical predicates that can select anything are positive integers.

Yes, I should've said "lower than or equal to". But "positive integers"
is better, because it also emphasizes that a predicate such as [3.14]
will never select anything.

>> 2) a sibling numerical predicate that is one is always redundant in a
>> pattern
> "Sibling numerical predicate" isn't one of your defined terms. I assume you mean a predicate of [1] preceded by another numerical predicate.

I thought it would be clear from the definitions of sibling predicates
and numerical predicates. But indeed, I meant a numerical predicate that
is also a sibling predicate, that has the effective static numeric value
of 1 (the integer, not the string), such like

[(1 to 20)[1]]

>> 3) a sibling predicate that is a sibling of a numeric predicate that is
>> higher than one never selects anything
>> Then, to make it tricky, what happens here, if the applied set is //foo?
>> (foo[2])[3]
> This never selects anything, but (.//foo[2])[3] does. The difference is that foo[2] always selects 0 or 1 elements, whereas .//foo[2] may select more than one.

I should have emphasized that I meant patterns, not expressions.
(.//foo[2])[3] is not allowed in a pattern. In XSLT 3.0, you can do
.[(.//foo[2])[3]] though, which gets interesting, but is not the same.

Let me try a few variants, for the excercise, and see if the same rules
still apply:

Selects of each second descendant element foo the second item
<xsl:apply-templates select="(//foo[2])[2]" />

Matches never, as foo[2] is always ever one node
<xsl:template match="(foo[2])[2]" />

Matches never, because of the singleton focus on the current node
<xsl:template match="(//foo[2])[2]" />

XSLT 3.0 syntax, matches if current node has at least two second foo
descendants (uncanningly unrelated to the select-expression (//foo[2])[2]).
<xsl:template match=".[(.//foo[2])[2]]" />

Note that the above is not equal to this:
<xsl:template match=".[(//foo[2])[2]]" />

The matching pattern that selects the same node as the expression
(//foo[2])[2] is, I think, node()[2]/foo[2], assuming the
apply-templates is done on a selection that includes these foo elements.

Hmm, not quite. Because the pattern does not have a relation to the
context item that was used during evaluation of the expression, but it
gets close.

>> Bottom line is, I think, that creating multiple sibling numerical
>> predicates is (usually) counter-productive and won't match anything when
>> used in a pattern (unless the number is "1", in which case it is also
>> redundant).
> More generally, an expression using a numeric predicate returns a value with cardinality 0:1, and applying a numeric predicate to a value with cardinality 0:1 is pointless.

Yes, that's a lot clearer and more generally applicable.

Current Thread