2

XSL:

<xsl:template match="int" 
              xmlns:fib="java:FibonacciNumber">
    <int>
      <xsl:value-of select="fib:calculate(number(.))"/>
    </int>
</xsl:template>

Groovy:

    import java.math.BigInteger
    import javax.xml.transform.TransformerFactory
    import javax.xml.transform.stream.StreamResult
    import javax.xml.transform.stream.StreamSource
    import javax.xml.transform.Templates


        class FibonacciNumber {
        def calculate(int n) {  
            if (n <= 0) {
              throw new IllegalArgumentException(
               "Fibonacci numbers are only defined for positive integers"
              )
            }
            BigInteger low  = BigInteger.ONE
            BigInteger high = BigInteger.ONE    
            for (int i = 3; i <= n; i++) {
              BigInteger temp = high
              high = high.add(low)
              low = temp
            }    
            return high  
          }
        }
def fibo = new FibonacciNumber()
def factory = TransformerFactory.newInstance()
def StreamSource xsource = new StreamSource(new File("validPathToXSL.xsl"))
def Templates template = factory.newTemplates(xsource)
def transformer = template.newTransformer()

transformer.setParameter("fib",fibo)

    transformer.transform(
    new StreamSource(
        new File("validPathToXmlFile.xml")), 
        new StreamResult(System.out)
        )

everytime i run a groovy-based transofrmation (from the groovyConsole) Groovy is complaining about not finding the class FibonacciNumber i tried to print the print this.class.getName() and print this.class.getPackage() and i only get the Names and null for each getPackage.

how would you reference the FibonacciNumber groovy class in your xslt to use its methods within the xsl Transformation ?

thanks

2
  • 1
    Punctuation would make it easier to read and understand your question. Especially to show where one sentence ends and the next begins. Commented Nov 28, 2011 at 16:11
  • How do you run the XSLT processor from the groovy console? How do you add the class to the classpath? Commented Nov 28, 2011 at 16:45

3 Answers 3

2

here is how it is solved:

instead of invoking the script from the groovyConsole just bundel everything into one groovy script that contains the code above and execute it using the main groovy interpreter from the command line. thats the only change i have made just running the script outside of the groovyconsole solved the classpath reference issue.

Sign up to request clarification or add additional context in comments.

Comments

1

Your implementation of a function that generates the n-th Fibonacci number is too-inefficient (linear).

An O(log(N)) algorithm exists. Also, it can easily be implemented entirely in XSLT, so your question how to integrate an extension function becomes totally unnecessary.

Below is the FXSL's f:fibo() function (implemented in XSLT 2.0). It is straightforward to convert this to XSLT 1.0:

 <xsl:function name="f:fibo" as="xs:integer" >
   <xsl:param name="pN" as="xs:integer"/>

   <xsl:sequence select=
    "if ($pN gt 10)
        then
          if($pN mod 2 = 0)
            then
               for $i in $pN idiv 2,
                         $fi in f:fibo($i),
                         $fi-1 in f:fibo($i -1)
                           return $fi*$fi + $fi-1*$fi-1
                  else
                     for $i in ($pN -1) idiv 2,
                         $fi in f:fibo($i),
                         $fi-1 in f:fibo($i -1)
                           return (2*$fi-1 + $fi) * $fi
              else
                (1,1,2,3,5,8,13,21,34,55,89)[$pN +1]
    "/>
 </xsl:function>

Here is a test that calculates the 3000th Fibonacci number:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:saxon="http://saxon.sf.net/"
 xmlns:f="http://fxsl.sf.net/"
 exclude-result-prefixes="xs saxon f" 
 >
  <xsl:import href="../f/func-Fibonacci.xsl"/>

 <xsl:output method="text"/>

  <xsl:template name="initial" match="/">
   The Fibonacci's number F3000:
<xsl:text/>
   <xsl:value-of select="f:fibo(3000)"/>
  </xsl:template>
</xsl:stylesheet>

The result (a 628 - digit number) is calculated and printed in 53 milliseconds:

664390460366960072280217847866028384244163512452783259405579765542621214161219257396449810982999820391132226802809465132446349331994409434926019045342723749188530316994678473551320635101099619382973181622585687336939784373527897555489486841726131733814340129175622450421605101025897173235990662770203756438786517530547101123748849140252686120104032647025145598956675902135010566909783124959436469825558314289701354227151784602865710780624675107056569822820542846660321813838896275819753281371491809004412219124856375121694811728724213667814577326618521478357661859018967313354840178403197559969056510791709859144173304364898001

See the pure XSLT solution of this project Euler problem -- here:

“The Fibonacci sequence is defined by the recurrence relation:

Fn = Fn1 + Fn2 , where F1 = 1 and F2 = 1. It turns out that F541 , which contains 113 digits, is the first Fibonacci number for which the last nine digits are 1-9 pandigital (contain all the digits 1 to 9, but not necessarily in order). And F2749 , which contains 575 digits, is the first Fibonacci number for which the first nine digits are 1-9 pandigital.

Given that Fk is the first Fibonacci number for which the first nine digits AND the last nine digits are 1-9 pandigital, find k.”

The XSLT solution is 55 lines long and runs for 0.555 seconds to generate and output the wanted Fibonacci number that has more than 68000 digits.

Explanation:

The f:fibo() function implemented by the transformation above is based on the following identities:

F(2n)   =  F(n)^2 + F(n-1)^2

F(2n+1) = (2*F(n-1) + F(n)) * F(n)

7 Comments

your implementation of fibionacci is indeed very efficient but that is not the focus here, i the interaction between xslt and groovy is the main issue here the question was you would reference a groovy based class in your xslt since the package is not known.
@user553222: Then provide an example where an extension function is really needed. In this particular case your extension function is much slower than the pure XSLT implementation.
@user553222: I don't know what is "GROOVY" (is this Java-based?), but as far as XSLT is concerned, there is no need at all to use an extension function for this problem -- not to mention that the provided extension function is significantly slower than the pure XSLT implementation. If you need to implement and use extension functions, read the appropriate section of your XSLT processor's documentation. For Saxon, read the guidance here: saxonica.com/documentation/extensibility/intro.xml
here is how i solved it for now: instead of invoking the script from the groovyConsole i just bundeled everything into a groovyscript which contains the code above and iam invoking the interpreter using the main groovy interpreter from the command line. thats the only change i have made just running the script outside of the groovyconsole solved it still i know that one can reference the class withing the groovyconsole but i dont know how i will close this one and open a new question related to referencing/fqn of a class created within the console. thanks!!
@AaronDigulla: The OP and the Groovy docs just provide an example of what shouldn't be coded as extension function. The OP could have just asked: "Please, give me a working example of writing and using an extension function". But instead, he is asking how to write and use an extension function that generates the n-th Fibonacci number. I answered to the question in the form it is written and I believe that my answer is probably the most useful answer to this question and that it would eliminate a lot of unproductive time for the OP and make his programs run factors of magnitude faster.
|
0

I have not tried this, as I'm not a Groovy user, but I suspect you need to put your FibonacciNumber class in a separate jar file that's in your classpath.

The XSLT transformer instance probably has no knowledge of the code that surrounds its creation.

Are you trying to adapt this chapter to Groovy?

1 Comment

Are you trying to adapt this chapter to Groovy? more or less yes background, i have a similar constallation where im using groovy hence im indeed adapting that one or mapping it into groovy

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.