Re: [xsl] Input requested for a good genuine example of the best parts of XSLT 2

Subject: Re: [xsl] Input requested for a good genuine example of the best parts of XSLT 2
From: Rashmi Rubdi <dev_subscriptions@xxxxxxxxx>
Date: Wed, 24 Jan 2007 13:55:24 -0800 (PST)
Hi Abel, 

XSLT 2.0 uses XPath2.0 which comes with more fuctions and better
syntax in comparison with the previous versions. 

For example 2.0 has an
extensive set of date functions, it has a function dedicated to convert upper
case to lower case unlike 1.0. 

Some of us don't have a choice but to stick
with XSLT1.0 for a while, until the dependent technologies implement the
features of XSLT2.0.

Given that XSLT2.0 and XPath2.0 attained W3C
recommendation status only a day ago, it will take time before dependent
technologies like Xalan upgrade from XSLT1.0 to 2.0
until then, those who use
Xalan have to stay with XSLT1.0. 

Otherwise using the latest version of XSLT
is as simple as, using better and easier features. 

Are you trying to
translate everything written in XSLT1.0/XPath1.0 to their 2.0 version?
-Rashmi

----- Original Message ----
From: Abel Braaksma
<abel.online@xxxxxxxxx>
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Sent: Wednesday,
January 24, 2007 2:30:50 PM
Subject: [xsl] Input requested for a good genuine
example of the best parts of XSLT 2


Hi people,

During the ongoing
discussion about XSLT 2 today and considering/not 
considering the switch, I
thought: why isn't there a nice 
all-encompassing example that shows the
merits of XSLT 2 over XSLT 1? 
It'll come as no surprise that there's no
trivial answer to that, so I 
figured: why not ask the masses (some people
claim that the masses are 
always right, though that is debatable).

The
target audience is: XSLT 1 users that would like to know more / 
understand
more of XSLT 2 and are considering the switch.

Before we start discussing the
template itself, let me throw in some rules:

     1. The template must be
100% compliant to the REC
     2. There can be no extensions used of whatever
kind
     3. The template must be rather simple, easy, explainable.
     4. It
must be run on itself (i.e., no hassle with input files etc)
     5. It must
show some key concepts, without showing too much detail
     6. Does not use
functions that call or write resources 
(xsl:result-document, unparsed-text
etc)
     7. (optional) it should be runnable on the available xslt 2
processors

Apart from (6) and (7), I think it is fairly trivial. I put in (7)
so 
that people that want to see other tools in action (Saxon, Gestalt,
Altova) can see them in action (it follows that this means no SA 
behavior,
sorry). I put in (6) to keep the example rather trivial. If 
users of
mentioned and/or missing tools would be so kind as to answer 
with a one-liner
to call the template below from a command line?

About the details that should
be in the example. I thought of a nice 
example that can possibly be made
infinitely better. Consider it a first 
draft, and I invite everyone to shoot
at it (you may even blast it away ;)

This what I put in so far:
   a) badly
designed xml as input (in a variable, see rule 4)
   b) a micro pipeline
   c)
for-each-group based on value to show groups without Muenchian
   d)
xsl:function for camelcasing a string
   e) ranges, like "2 to 3" and
comparison
   f) tokenize() and matches()
   g) for ... in .... return
   h)
next-match
   i) the use of the 'as' attribute on basic processors

The
example is rather trivial (it should be, I believe). It takes a list 
of users
of XSLT products, and groups them per product:

  <james-johnsson>Saxon, c,
xslt 2</james-johnsson>
  <super-troopers>xsltproc, nc, xslt
1</super-troopers>

Here: the node name is the user. Then follows a CSV
string. The first 
part is the processor, the second says Compliant or
NonCompliant, the 
third says the language (I am pretty sure the input is not
correct, 
sorry about my lack of knowledge of the compliancy level).

The
output groups per processor as follows, where some processing is 
done on the
strings and the users are comma-concatenated under <users>:

<processor
name="Xsltproc">
   <level>processor is non-compliant</level>
<language>XSLT 1</language>
   <users>George Williams Geraldson, Super
Troopers</users>
</processor>


I understand this is a rather superficial
example. If anybody can make 
it better, clearer, input is welcome. Keep in
mind that it should be 
kept easy as well as showing the power of XSLT 2 (so
it can be used as a 
showcase).

Here's the XSLT so far, any ideas,
complaints, suggestions, rewrites, 
opinions etc are welcome:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";;
    xmlns:xs =
"http://www.w3.org/2001/XMLSchema";;
    xmlns:my = "urn:my"
    version="2.0"
exclude-result-prefixes="#all">

    <xsl:output indent="yes" />
   
    <!--
the input, just in a variable
        ready to use, easy for testing, no need
for exslt:node-set()
    -->
    <xsl:variable name="preferences">
<james-johnsson>Saxon, c, xslt 2</james-johnsson>
<george-williams-geraldson>xsltproc, nc, xslt 
1</george-williams-geraldson>
<super-troopers>xsltproc, nc, xslt 1</super-troopers>
<merry-mirriams>libxslt, nc, xslt 1</merry-mirriams>
<john-ronald-reuel-tolkien>saxon, c, xslt 
2</john-ronald-reuel-tolkien>
<sir-tomald-richards>gestAlt, nc, XSLT 2</sir-tomald-richards>
<agatha-kirsten>saxon, c, xslt 2</agatha-kirsten>
<mollie-jollie>saxon, c, xslt 2</mollie-jollie>
    </xsl:variable>
<xsl:template match="/" name="main">
        <xsl:variable
name="micro-pipeline">
            <xsl:apply-templates
select="$preferences/*" />
        </xsl:variable>
       
        <!-- group
by processor -->
        <xsl:for-each-group
select="$micro-pipeline/processor"
group-by="token[1]/upper-case(text())">
           
            <processor
name="{my:camel-case(token[1])}" >
                <xsl:apply-templates
select="token[position() = 2 to 3]" />
                <users>
<!--
                        join the users in one string
and camel case their names
                    -->
<xsl:value-of select="
                        string-join(
my:camel-case(current-group()/user)
                        , ', ')" />
</users>
            </processor>           
        </xsl:for-each-group>
</xsl:template>
   
    <!--
        matches for $preferences nodes
    -->
<xsl:template match="*" priority="0">
        <processor>
<xsl:next-match />
        </processor>
    </xsl:template>

    <xsl:template
match="*">
        <user><xsl:value-of select="local-name(.)" /></user>
<xsl:next-match />
    </xsl:template>
   
   
    <xsl:template
match="text()">
        <xsl:for-each select="tokenize(., ',')">
<token><xsl:value-of select="normalize-space(.)" /></token>
</xsl:for-each>
    </xsl:template>
   
   
    <!--
        what follows:
matches for micro pipeline
        all matches are case-insensitive, with no
need for translate() and trouble with more complex
        characters
    -->
<xsl:template match="token[matches(., '^c$', 'i')]">
        <level>processor
is compliant</level>
    </xsl:template>
   
    <xsl:template
match="token[matches(., '^nc$', 'i')]">
        <level>processor is
non-compliant</level>
    </xsl:template>
   
    <xsl:template
match="token[matches(., '^xslt', 'i')]">
        <language><xsl:value-of
select="upper-case(.)" /></language>
    </xsl:template>
   
    <!--
put the nasty bit aside in a function
        it camel-cases a dashed or space
delimited string
    -->
    <xsl:function name="my:camel-case"
as="xs:string*">
        <xsl:param name="string" as="xs:string*"/>
<xsl:sequence select="for $s in $string
            return string-join(
for $word in tokenize($s, '-| ')
                return
concat(
                        upper-case(substring($word, 1, 1)),
substring($word, 2))
                , ' ')" />
    </xsl:function>
</xsl:stylesheet>



Cheers,
-- Abel Braaksma
   http://www.nuntia.nl
_____________________________________________________________________________
_______
We won't tell. Get more on shows you hate to love 
(and love to hate):
Yahoo! TV's Guilty Pleasures list.
http://tv.yahoo.com/collections/265

Current Thread