Re: Fwd: Pattern matching error in xsl:key

Chapman Flack <chap-JULfBfA8satPFr4CO1/[email protected]> Sun, 6 Sep 2020 11:51:03 -0400
Newsgroups gmane.text.xml.saxon.help
Message-ID <[email protected]>
On 09/05/20 14:37, Ihe Onwuka wrote:
> That's the reason the spec gives. I asked for the logical reason.
> 
> Perhaps you feel they are one and the same to me they are not because they
> produce the  illogical end result that two things that are obviously equal
> are not

Here's why I agree it's the logical reason.

The best way anyone has ever come up with to design a language that is
usable for writing predictable and dependable programs is to give it
rules that are clearly stated and always applied. That doesn't make it
effortless to learn or use: you do have to learn what the rules are.
But once you have, you always know what it's going to do.

In this case, you have to keep in mind there are two specs involved.
XML has a spec. Already had one before XSLT was specified. And XSLT
also has a spec (for this purpose, we'll say XPath is part of that).
AND when you write out XSLT, you write it in XML. You write a program
for operating on XML, in the language XSLT, and that program is written
out in XML form itself. That's just the basic landscape; anybody using
it has to remember that.

So the comment
> I am comparing parameters whose values are 4.0 and 4.1 respectively to
> attributes whose values are 4.0 and 4.1 respectively. Saxon has made it's
> own assumptions about what types they are

isn't really on point. Saxon hasn't made assumptions about what types they
are, it has given them the types of what you wrote.

This comment was more on point:

> you've basically got a situation where the spec is assigning
> different types to the same identical value because they are
> placed in different constructs.

Well yes, yes exactly. As the human, it's your job to learn what the
different constructs mean. XSLT is just always going to do what you have
told it to do.

In your *data*,

<changes from="math:exp(1)" to="math:pi()"/>

is just the XML document you're operating on, it's data, and that's an
XML element with two attributes, they are xs:untypedAtomic and each one
has a value that starts with 'm' and ends with ')'.

In your *program*,

<xsl:param name="source" select="math:exp(1)"/>
<xsl:param name="target" select="math:pi()"/>

is in the form of XML, sure, but it isn't just data, it's your program,
with the semantics of XSLT. Those select attributes are expressions, and
they have values of type xs:double, somewhere around 2.71 and 3.14, and
will not match the <changes> element above.

It is up to you to remember where you're writing literals and where you're
writing expressions. That can't really be made easier. The language rules
are consistent and once you are using them consistently they won't surprise
you anymore.

Now, there's a choice of different ways the <param> could be rewritten.
As suggested upthread, just doing this won't work:

<xsl:param name="target" select="4.0" as="xs:string"/>

It would earn you a "required type is xs:string, supplied value is
xs:decimal" error, just as String target = 4.0; would in Java.

Here are two other choices:

<xsl:param name="target" select="4.0 cast as xs:string"/>

<xsl:param name="target" as="xs:string">4.0</xsl:param>


Both of them will give you a string, but they will give you different
strings. The first one is an expression that produces 4.0 as a decimal
value and then casts it to xs:string; by the rules of number-to-string
casting, that will come out "4", not "4.0".

The second one will take the xs:untyped 4.0 appearing in the content
and cast it directly to xs:string, producing "4.0". Probably that is
the construct you would want to use.

Once those rules are familiar, you can confidently rely on them.

Regards,
-Chap