Re: [xsl] FizzBuzz in XSLT 1.0. Help with a 2.0/FXSL solution?

Subject: Re: [xsl] FizzBuzz in XSLT 1.0. Help with a 2.0/FXSL solution?
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Wed, 14 Mar 2007 22:13:22 +0100
M. David Peterson wrote:
I been bouncing around different ideas in my head all morning as to the best way to optimize this in XSLT 2.0/FXSL, but as of yet, haven't come up with something that I think really takes advantage of what XSLT 2.0/FXSL bring to the table. Ideas from the community at large?

Hi David,


Though others have already provided good solutions, I couldn't resist upon reading your request. Coming from a Perl world, I like one-liners, and though very much against any spirit of clear code, here's a version that does away with if-statements altogether (oops, I see now that David C's second approach already had that).

I agree with David C that a slightly different input XML would make the code a fair amount more readable. With the proposed start/end it looks like this (quite like David's simplified example):

<xsl:template match="fizzbuzz">
<xsl:value-of separator="&#10;"
select="for $i in start to end
return ((string-join(test/mod[$i mod @value = @test], ''))[.], $i)[1]" />
</xsl:template>



With the original input document, however, my attempt looks like this:


<xsl:template match="fizzbuzz">
<xsl:value-of separator="&#10;"
select="
for $i in range/xs:integer(tokenize(., '\D')[1])
to range/xs:integer(tokenize(., '\D')[last()])
return (string-join(test/mod[$i mod @value = @test], '')[.], $i)[1]" />
</xsl:template>



Note that there's a slight change in semantics for the range value (now any separator works). I.e.:


<!-- outputs 'FizzBuzz' -->
<range>54390</range>

<!-- outputs '4 Buzz Fizz 7' -->
<range>4 to 7</range>

<!-- outputs all up to 100 -->
<range>1-100</range>

The oddbit in my code (well, it took me some time to get it right) is the string-join. Most functions return an empty sequence when provided with an empty sequence, but not string-join, hence the rather awkward conversion to a sequence and testing for self: string-join(inp-seq, '')[.]

This returns an empty sequence when it string-join returns an empty string, which will be factored out, hence the following: ((), $i)[1] will return the last value.

Thanks for the exercise ;)

Cheers,
-- Abel Braaksma
  http://www.nuntia.nl

Current Thread