xsl-list
[Top] [All Lists]

Re: Re: Re: The Perils of Sudden Type-Safety in XPath 2.0

2003-02-20 02:42:21
Dimitre,

I'm not disagreeing with your position. I have had some fundamental
objections to the introduction of data-typing within XSLT almost from the
moment that it first appeared in the specifications. I've worked with XSLT
often enough to state that the number of times I can point to where static
typing would have come in handy can be counted on one hand, and usually
there was some work-around there. I see the type mechanisms as a big step
backwards, but one that is unfortunately driven by a few vendors
(principally Microsoft) who are convinced that dynamic typing is bad and
dangerous. I can think of a few cases where I would agree, but many more
where dynamic typing is far preferable to dealing with static type.

As to the function mapping, I'm a little more ambivalent. The example I gave
there was pedagogical in nature, meant to illustrate the principle. I do
believe, however, that the principle advantage that there are two principle
advantages of the <xsl:function> element:

1) It makes it easier to develop a consistent set of libraries that can be
utilized repeatedly. You may end up using this function only once in a given
stylesheet, but if you use the same function imported into multiple
stylesheets then you've significantly reduced your overhead.

2) It makes it possible to create class-like architectures within well
defined namespaces, a definite plus as I see it in creating a comprehensive
framework for development. For instance, you can define a matrix namespace:

<!-- matrix.xsl -->
<xsl:stylesheet xmlns:xsl="..."
                      xmlns:mat='http://www.mynamespaces.com/mat'
                      version='2.0'>

<xsl:function name="mat:new">

</xsl:function>

<xsl:function name="mat:cross_product">
...
</xsl:function>

<xsl:function name="mat:dot_product">
...
</xsl:function>

<xsl:function name="mat:add">

</xsl:function>

...
</xsl:stylesheet>

Given that, you've essentially created an object called matrix: with an
associated set of methods.

<xsl:stylesheet xmlns:xsl="..."
                       xmlns:matrix='http://www.mynamespaces.com/mat'
                       version='2.0">
<xsl:import href="matrix.xsl"/>

<xsl:template match="foo">
    <xsl:variable name="mat1"
select="matrix:new(3,3,(1,1,0,0,1,0,-1,0,1))"/>
    <xsl:variable name="mat2" select="matrix:new(3,3,(1,0,1,1,1,0,1,1,0))"/>
    <xsl:variable name="matResult" select="matrix:add($mat1,$mat2)"/>
    ...
</xsl:template>

</xsl:stylesheet>

Admittedly, you've inverted the traditional class structure somewhat:
$mat1.add($mat2) becomes matrix:add($mat1,$mat2), but this to me is a
relative formality. Most significantly in the above case, you've created an
abstraction mechanism - you don't need to know what the underlying structure
of a matrix object is, only that it behaves consistently. Perhaps as
importantly, a structure is introduced without needing to have any explicit
typing mechanism in place.

Now, the question can legitimately be asked about whether I'd want to do
complex matrix mathematics in XML, though to be honest I don't think it is
as far fetched as it sounds. I could definitely see it being used in X3D
generation, for instance. At any rate, this library serves to not only
abstract out the underlying implementation (I could, for instance, use an
external Java class or C# class to do the actual matrix multiplication,
depending upon platform) but also to more intelligently organize functions.

This gets me back to a gripe that I've had about the XPath2/XQuery
functions, one which, to date, I've still not received a satisfactory answer
about (other than "oh, it's too late to make changes at this point", told to
me about six months ago). There are a huge number of date functions within
the specs, that seem to cause no end of trouble from an implementation
standpoint, and that seem to provide relatively little benefit save as
mechanisms to more easily extract date content.

It seems to make so much more sense to me to build an import facility into
XQuery akin to <xsl:import> (something that's frankly a necessity anyway,
since the same argument about the utility of "one-off" functions in XSLT2
applies to XQuery in spades) and then put the date functions (including the
date types, more on that in a moment) into their own namespace. In XSLT,
you'd have:

<!-- dateTime.xsl -->
<xsl:transform ... xmlns:dateTime=http://www.w3.org/xquery/ns/dateTime>
    <xsl:function name="new">
        ...
    </xsl:function>

    <xsl:function name="get_month">
        ...
    </xsl:function>

    <xsl:function name="get_full_year">
        ...
    </xsl:function>

    <!-- and so forth -->
</xsl:transform>

<!-- dateTimeTest.xsl -->
<xsl:stylesheet ... xmlns:dateTime="http://www.w3.org/xquery/ns/dateTime";>
    <xsl:template match="foo">
        <xsl:variable name="myDate"
select="dateTime:new('2003-02-18T00:00:00')"/>
        <xsl:variable name="month" select="dateTime:get_month($myDate)"/>
        <xsl:variable name="year" select="dateTime:get_full_year($myDate)"/>
    </xsl:template>
</xsl:stylesheet>

In XQuery you'd use a similar syntax:

import namespace 'http://www.w3.org/xquery/ns/dateTime' as 'dateTime'
let $myDate:=dateTime:new("2003-02-18T00:00:00")
return
    <date>
        <month>{dateTime:get_month($myDate)}</month>
        <year>{dateTime:get_full_year($myDate)}</year>
    </date>

In a situation like this, the namespace prefixes essentially act like class
identifiers. It gives you "type" characteristics, avoids namespace
collisions, reduces the size of the core XQuery/XPath2 function spec to
about a third of its present size, and allows for extensibility.

You can also use it to create more effective wrapper functions. For
instance, you could create a double: namespace that encapsulates the
xsi:double data-type:

<xsl:transform ... xmlns:double='http://www.w3.org/xquery/ns/double'>

<xsl:function name="double:new">
    ....
</xsl:function>

<xsl:function name="double:value".
   ...
</xsl:function>

<xsl:function name="double:toInteger".
   ...
</xsl:function>

<xsl:function name="double:toString">
    ...
</xsl:function>
</xsl:transform>

This would let you do

<xsl:variable name="dbl" select="double:new(100.5)"/>
<xsl:variable name="result" select="double:value($dbl) * 110.2"/>
<xsl:value-of select="double:toString($result)"/>

or, in XQuery,

let $dbl :=double:new(100.5)
let $result := double:value($dbl) * 110.2
return <result>{double:toString($result)}</result>

The other advantage to this approach is that you can define a set of
standard conversion functions for each data type in this way that are able
to sense the appropriate context and map implicitly (i.e., $dbl is
equivalent to double:value($dbl) when forced into a cast with a double,
double:toString($dbl) when forced into a cast with a string, and so forth.
Yes, it is marginally more verbose, but at least if you're remotely familiar
with OOP it makes a lot more sense than trying to create a superlibrary with
no underlying organization on that library.

-- Kurt



----- Original Message -----
From: "Dimitre Novatchev" <dnovatchev(_at_)yahoo(_dot_)com>
To: <xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com>
Sent: Thursday, February 20, 2003 12:18 AM
Subject: Re: [xsl] Re: Re: The Perils of Sudden Type-Safety in XPath 2.0



--- "Kurt Cagle" <cagle(_at_)olywa(_dot_)net> wrote:
Dmitre,

I'm inclined to agree with Michael on this. I think that the type
mechanisms
do add (perhaps an unreasonable) burden in verbosity, but that is
more
than
offset by the ability to move a significant amount of the heavy
lifting
into
XPath through <xsl:function>

<xsl:function name="fmt:bangPad">
    <xsl:param name="expr"/>
    <xsl:result
select="string-pad('!',xs:string(xs:integer($expr)))"/>
</xsl:function>

<xsl:value-of select="fmt:bangPad(@risk * @severity)"/>


Kurt,

This is a nice example!

But the truth probably lies somewhere in-between.

There will be cases when many functions are used in a stylesheet, but
most of them are used *only once*. Providing a wrapper xsl:function for
every such function will increase the length of the code significantly.

One can argue that probably third-party libraries of such wrappers will
be available, so one will need only to xsl:import them.

But if this happens, this would mean that something in the design of
the standard functions was not OK.

Let's return to the example of string-pad(). Would it not be a better
decision to allow any number as the type of the second argument?

Then people would have to use the familiar conversion number(x) and
this would facilitate the transition to XSLT2 for most of the XSLT1
folks. Let's face it -- most people (me included) do not feel
comfortable that they must use schemas with XSLT2. Even declaring the
namespace and using the prefix can be a considerable psychological
burden (sorry for going into Jeni's territory).

This will also address Chuck's concern that the XSLT2 programmer will
have to do an "awful lot of cross-referencing to grok it all (go look
at the XQuery function and operator spec, then go look at XPath, then
go back to the XSLT spec to see how to use something else)".

And let's not try to mislead anyone that xs:integer was chosen because
it was the exact type for this function -- it isn't the exact type.
Anyone can still pass a negative integer to string-pad() and no static
type-checking will help.

So, the authors of XQ/XP functions/operators decided to draw the line
somewhere, but should have drawn it on allowing any number, not just
integer.

Probably we need to start some real work using Saxon 7.x and have a
separate forum for discussing the real-work experience.

I also will join the people appreciating highly the huge work done by
Mike Kay and his advice on XSLT2 (and not least having to deal with
people like myself :o))





=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL

__________________________________________________
Do you Yahoo!?
Yahoo! Tax Center - forms, calculators, tips, more
http://taxes.yahoo.com/

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list




 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list