Re: [xsl] evaluation of predicate using | mistyped as ||

Subject: Re: [xsl] evaluation of predicate using | mistyped as ||
From: "Michael Kay mike@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 11 Apr 2024 20:42:07 -0000
The '||' operator has lower precedence than '|', so the predicate means

> (descendant::foo | self::foo) || ancestor::foo

So it evaluates both operands of '||' as node-sets, atomizes the results,
concatenates them, and the predicate is true if the result of the concatation
is a non-empty string.

In 3.1 the operands of '||', like the arguments of concat(), must be of type
xs:string?, in 4,0 they can be of type xs:string*. But as you say, if a type
error occurs in 3.1 it will occur dynamically and will be masked, causing the
pattern to evaluate as false.

Michael Kay
Saxonica


> On 11 Apr 2024, at 21:08, Martin Honnen martin.honnen@xxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
>
> I wrote a stylesheet where I wanted to use a template with a match
> pattern doing a union
>
>   <xsl:template match="node()[descendant::foo | self::foo |
> ancestor::foo]">
>     <xsl:copy>
>       <xsl:apply-templates/>
>     </xsl:copy>
>   </xsl:template>
>
>
> but I managed to mistype the second union | as a concat || and I first
> didn't notice other than wondering why my code didn't work as intended:
>
>   <xsl:template match="node()[descendant::foo | self::foo ||
> ancestor::foo]">
>     <xsl:copy>
>       <xsl:apply-templates/>
>     </xsl:copy>
>   </xsl:template>
>
> Now I wonder on how node()[descendant::foo | self::foo || ancestor::foo]
> is evaluated but I am not sure.
>
> Any idea what is supposed to happen if a union operator | and a concat
> operator || are used in that way in the same predicate of a pattern? I
> guess a type error and the pattern matches generating the type error
> would be ignored.
>
> Any idea in which way/order
>
>   descendant::foo | self::foo || ancestor::foo
>
> would be evaluated?
>
> For what it's worth, Saxon 12 for an input like
>
> <root>
>   <div>
>     <foo>a</foo>
>     <bar>1</bar>
>     <foo>b</foo>
>     <baz>2</baz>
>   </div>
> </root>
>
> and a complete stylesheet like
>
> <?xml version="1.0" encoding="utf-8"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>   version="3.0"
>   xmlns:xs="http://www.w3.org/2001/XMLSchema";
>   exclude-result-prefixes="#all">
>
>   <xsl:template match="node()[descendant::foo | self::foo ||
> ancestor::foo]">
>     <xsl:copy>
>       <xsl:apply-templates/>
>     </xsl:copy>
>   </xsl:template>
>
>   <xsl:mode on-no-match="shallow-skip"/>
>
> </xsl:stylesheet>
>
> gives a single warning
>
> Warning at char 7 in xsl:template/@match on line 7 column 78 of sheet3.xsl:
>   XPTY0004  An error occurred matching pattern {node()[descendant::foo
> | self::foo ||
>   ancestor::foo]}: A sequence of more than one item is not allowed as
> the first argument of
>   fn:concat() (<foo>, <foo>)
>
>
> I can see how descendant::foo can select two foo elements but wouldn't
> that happen twice, namely for the "root" element and for the "div"
> element? Shouldn't there be two such warnings?

Current Thread