- From: Michael Kay <mhkay@iclway.co.uk>
- Date: Fri, 20 Jul 2001 07:37:30 +0100
- To: "'Richard A. O'Keefe'" <ok@atlas.otago.ac.nz>, <xsl-editors@w3.org>
(Unofficial response) The requirement to write extension functions in XSLT is recognized, and is included in the published requirements list for XSLT 2.0. Meanwhile, independently of W3C, a group of users have put together a specification of a similar facility at http://www.exslt.org/, and this has been implemented in some vendors' XSLT 1.0 products. Mike Kay > -----Original Message----- > From: w3c-xsl-wg-request@w3.org [mailto:w3c-xsl-wg-request@w3.org]On > Behalf Of Richard A. O'Keefe > Sent: 20 July 2001 06:03 > To: xsl-editors@w3.org > Subject: Let's write extension functions in XSLT itself > > > I downloaded the 12-Dec-2000 draft of the XSLT 1.1 recently. > I notice that there is to be a standard way of defining functions > that can be called in patterns and expressions, provided those > definitions are in JavaScript or Java. That's really really odd. > You can write part of a style sheet in a language which the processor > might NOT support, but you you can't write it in a language which > the processor MUST support. > > I enclose a proposal for defining extension functions in XSLT itself. > It would be absurd to call out to Javascript (non-portably!) just > because some calculation can't be expressed in the expresison language > for want of an 'if' construct. > > ---------------- cut here ---------------- > <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN"> > <!-- File : xslt-funs.htm > Author : Richard A. O'Keefe > Updated: 2001.07.19 > Purpose: Propose a way to define extension functions in > XSLT itself. > --> > <HTML> > <HEAD> > <TITLE>Defining Extension Functions in XSLT Itself</TITLE> > </HEAD> > <BODY> > <H1>Defining Extension Functions in XSLT Itself</H1> > <P>Looking at the 12 December 2000 version of the > XSL Transformations (XSLT) Version 1.1 specification, > we see that there is to be a standard way of defining functions > that can be called in patterns and expressions, provided those > definitions are in JavaScript or Java.</P> > <P>This is a very odd state of affairs. You can write part of a style > sheet in a language which the processor may <EM>not</EM> support. But > you can't write it in a language which the processor <EM>must</EM> > support.</P> > <P>Experience with XSLT has already shown that the inability to define > functions in the expression language can result in code duplication. > For example, you cannot say "a DIV1, ..., DIV4 are processed > identically except for using H2, ..., H5 respectively".</P> > <H2>What we can do about it</H2> > <P>I propose a single new top level element in the XSLT namespace, > with three new elements that can appear in it. First I present the > specification using DTD syntax, then I explain it.</P> > <PRE> > <!ENTITY % type "(Boolean|number|string|node-set|object|any)"> > <!ELEMENT xsl:function > (xsl:required*,((xsl:case+,xsl:else)|xsl:value-of))> > <!ATTLIST xsl:function > name NMTOKEN #REQUIRED > type %type; #REQUIRED> > <!ELEMENT xsl:required EMPTY> > <!ATTLIST xsl:required > name NMTOKEN #REQUIRED > type %type; #REQUIRED> > <!ELEMENT xsl:case EMPTY> > <!ATTLIST xsl:case > test CDATA #REQUIRED > select CDATA #REQUIRED> > <!ELEMENT xsl:else EMPTY> > <!ATTLIST xsl:else > select CDATA #REQUIRED> > </PRE> > <DL> > <DT><CODE>xsl:function</CODE></DT> > <DD>defines an extension function that can > be used in the expression language. It has a <CODE>name</CODE>, which > is a QName. If the name has a prefix, that prefix must have > been declared > as an extension prefix. If the name does not have a prefix, > <CODE>#default</CODE> must have been declared as an extension prefix. > The result type says which of the XSLT types the function is > supposed to > return.</DD> > <DT><CODE>xsl:required</CODE></DT> > <DD>defines a required formal parameter of the function. The > association between formal parameters in a definition and actual > parameters in a call is by position. In this draft, there are no > optional parameters; the number of parameters in a call must match the > number of parameters declared. Each parameter has a <CODE>name</CODE> > and a <CODE>type</CODE>; each actual parameter is converted to the > required type the same way that built-in functions in the expression > language are converted to expected types. The interpretation > and scope > of argument names is the same as the interpretation and scope of > <CODE>xsl:param</CODE> names; however there are no optional > or "keyword" > parameters for XSLT-in-XSLT extension functions.</DD> > <DT>xsl:case</DT> > <DD>is a construct we wouldn't need if only the designers of XPath had > included an "<CODE>if</CODE>" construction. Each > <CODE>xsl:case</CODE> > element is tested in document order until a <CODE>test</CODE> > expression > comes out true, and then the value of the corresponding > <CODE>select</CODE> > expression is the result of the function.</DD> > <DT>xsl:else</DT> > <DD>must appear at the end of a conditional construction; its > <CODE>select</CODE> attribute specifies what result to return > if none of > the <CODE>xsl:case</CODE> tests succeeds.</DD> > <DT>xsl:value-of</DT> > <DD>is used when the body of the expression is unconditional.</DD> > </DL> > <H2>Some examples</H2> > <P>Absolute value</P> > <PRE> > <xsl:function name="my:abs" type="number"> > <xsl:required name="x" type="number"> > <xsl:case test="$x < 0" select="-$x"> > <xsl:else select="$x"> > </xsl:function> > </PRE> > <P>Converting DIV to H</P> > <PRE> > <xsl:function name="my:div-to-h" type="string"> > <xsl:required name="node" type="node-set"> > <xsl:case test="$node[name()='div1'" select="'h2'"> > <xsl:case test="$node[name()='div2'" select="'h3'"> > <xsl:case test="$node[name()='div3'" select="'h4'"> > <xsl:case test="$node[name()='div4'" select="'h5'"> > <xsl:else select="h6"> > </xsl:function> > </PRE> > <P>Computing a label from a node</P> > <PRE> > <xsl:function name="my:label" type="string"> > <xsl:required name="node" type="node-set"> > <xsl:case test="$node/@id" select="concat('diff-',$node/id)"> > <xsl:else select="concat('diff-',generated-id($node))"> > </xsl:function> > </PRE> > <H2>Discussion</H2> > <P>This is basically XML syntax for wrapping "if" around a bunch of > expressions. It does not appear to require any fundamentally new > constructions in an XSLT processor; an entire definition should be > translatable into the internal form used for XSLT expressions.</P> > <P>There was a note at the end of XSLT 1.0 that conditional > expressions > should be considered for a future version of XSLT. If that were done, > then these function definitions could be simplified by leaving out > <CODE>xsl:case</CODE> and <CODE>xsl:else</CODE>.</P> > <P>Having a type in the <CODE>xsl:function</CODE> element means that > even should the different cases have different "natural" types, they > will be converted to a common form, unless the function is explicitly > typed as "<CODE>any</CODE>".</P> > <P>The <CODE>data-type</CODE> attribute used in sorting has a > sufficiently > different range of options that it did not seem wise to call the > <CODE>type</CODE> attribute used here <CODE>data-type</CODE>.</P> > <P>This feature would mean that style sheets could be more portable. > There are very strong reasons <EM>not</EM> to support Java; > measurements > with existing free XSLT processors shows Java versions running 2 to 5 > times slower than a C version, and taking a great deal of memory for > what seem like simple tasks. It would be as inappropriate for XSLT > in practice to <EM>demand</EM> Java support as it would be for XSLT > to <EM>forbid</EM> Java support. It would be especially regrettable > if XSLT were to encourage people to write non-portable scripts simply > in order to perform calculations that should be within its > own scope.</P> > <P>Whether <CODE>xsl:value-of</CODE> and > <CODE>xsl:else</CODE> should be > distinct elements is arguable.</P> > <P>Optional parameters are not in the present design, just to > keep it simple. > Another alternative would have</P> > <PRE> > <!ELEMENT xsl:function (xsl:required*,xsl:optional*, > ((xsl:case+,xsl:else) | xsl:value-of))> > <!ATTLIST xsl:optional > name NMTOKEN #REQUIRED > type %type; #REQUIRED > select CDATA #REQUIRED> > </PRE> > <H2>The End</H2> > <P>If you want to discuss this, my e-mail address is > <A HREF="mailto:ok@cs.otago.ac.nz">ok@cs.otago.ac.nz</A>.</P> > <p><a href="http://validator.w3.org/check/referer"><img border="0" > src="http://www.w3.org/Icons/valid-html32" alt="Valid HTML 3.2!" > height="31" width="88"></a></p> > </BODY> > </HTML> > ---------------- cut here ---------------- > > >
Received on Friday, 20 July 2001 02:33:53 UTC