Topic
19 replies Latest Post - ‏2012-10-10T20:22:05Z by Jrules80
BalajiAllam
BalajiAllam
7 Posts
ACCEPTED ANSWER

Pinned topic XSLT random number generation and assigning to a datapower context variable

‏2012-10-09T16:20:30Z |
Hi!

Here's what I am trying to do - I would want to generate a random number (hopefully a 4 digit #)using the Math:random() function in xslt and then assign it to a datapower context variable. For some reason, it is not working. Can I get some help on this, please?

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dp="http://www.datapower.com/extensions"
xmlns:math="http://exslt.org/math"
extension-element-prefixes="math">
<!--
Document : RandomNumGen.xsl
Created on : October 8, 2012, 3:21 PM
Author :
Description:
Purpose of transformation follows.
-->
<xsl:variable name="randNumb">
<xsl:value-of select="math:random()" />
</xsl:variable>

<dp:set-variable name="'var://context/header/RandomID'" value="$randNumb"/>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:bac="http://www.example.org/Backend1/">
<soapenv:Header/>
<soapenv:Body>
<bac:Response>
<Num>
<xsl:value-of select="$randNumb"/>
</Num>
</bac:Response>
</soapenv:Body>
</soapenv:Envelope>

</xsl:stylesheet>
Updated on 2012-10-10T20:22:05Z at 2012-10-10T20:22:05Z by Jrules80
  • swlinn
    swlinn
    1344 Posts
    ACCEPTED ANSWER

    Re: XSLT random number generation and assigning to a datapower context variable

    ‏2012-10-09T16:28:33Z  in response to BalajiAllam
    You need to place your code inside a <xsl:template match="/">all of your code</xsl:template> element. Your extension-element-prefixes="math" is also incorrect, should be extension-element-prefixes="dp". You should also add exclude-result-prefixes="dp math" as you don't want those namespaces in your SOAP output message

    Regards,
    Steve
    • BalajiAllam
      BalajiAllam
      7 Posts
      ACCEPTED ANSWER

      Re: XSLT random number generation and assigning to a datapower context variable

      ‏2012-10-09T16:33:54Z  in response to swlinn
      Hello Steve - Thanks for your quick response. I appreciate it! I am a noob to XSLT and DataPower, so please bear with my mistakes. Can you check if the below code is OK, please?
      <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:dp="http://www.datapower.com/extensions"
      xmlns:math="http://exslt.org/math"
      extension-element-prefixes="dp"
      exclude-result-prefixes="dp math" >
      <!--
      Document : RandomNumGen.xsl
      Created on : October 8, 2012, 3:21 PM
      Author : allambal
      Description:
      Purpose of transformation follows.
      -->

      <xsl:template match="/">
      <xsl:variable name="randNumb">
      <xsl:value-of select="math:random()" />
      </xsl:variable>

      <dp:set-variable name="'var://context/header/RandomID'" value="$randNumb"/>
      <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:bac="http://www.example.org/Backend1/">
      <soapenv:Header/>
      <soapenv:Body>
      <bac:Response>
      <Num>
      <xsl:value-of select="$randNumb"/>
      </Num>
      </bac:Response>
      </soapenv:Body>
      </soapenv:Envelope>
      </xsl:template>
      </xsl:stylesheet>
    • BalajiAllam
      BalajiAllam
      7 Posts
      ACCEPTED ANSWER

      Re: XSLT random number generation and assigning to a datapower context variable

      ‏2012-10-09T16:49:44Z  in response to swlinn
      Works like a charm. Thanks so much. Also, right now this is the result I am getting:

      <soapenv:Envelope
      xmlns:bac="http://www.example.org/Backend1/"
      xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
      >

      <soapenv:Header />
      <soapenv:Body>
      <bac:Response>
      <Num>0.01672205701470375</Num>
      </bac:Response>
      </soapenv:Body>

      </soapenv:Envelope>

      Is there a way I could actually truncate this number (0.01672205701470375) to 4 digits in an integer form? (no decimal places)
      • HermannSW
        HermannSW
        4357 Posts
        ACCEPTED ANSWER

        Re: XSLT random number generation and assigning to a datapower context variable

        ‏2012-10-09T18:33:21Z  in response to BalajiAllam
        > ...
        > Is there a way I could actually truncate this number (0.01672205701470375) to 4 digits in an integer form? (no decimal places)

        $ echo "<num>0.01672205701470375</num>" | xpath++ "concat(substring('000',string-length(floor(. * 10000))),floor(. * 10000))" -
        0167
        $
        


         
        Hermann <myXsltBlog/> <myXsltTweets/>
        Updated on 2014-03-25T02:48:13Z at 2014-03-25T02:48:13Z by iron-man
        • JRules
          JRules
          5 Posts
          ACCEPTED ANSWER

          Re: XSLT random number generation and assigning to a datapower context variable

          ‏2012-10-09T18:38:01Z  in response to HermannSW
          Hermann - How could I achieve the truncation in XSLT? I did not follow your code? Can you please plug it the xslt solution?
          • HermannSW
            HermannSW
            4357 Posts
            ACCEPTED ANSWER

            Re: XSLT random number generation and assigning to a datapower context variable

            ‏2012-10-09T18:49:26Z  in response to JRules
            > ... Can you please plug it the xslt solution?
            >
            ...
            <Num>
            <xsl:value-of select="concat(substring('000',string-length(floor($randNumb * 10000))),floor($randNumb * 10000))"/>
            </Num>
            ...
            


             
            Hermann <myXsltBlog/> <myXsltTweets/>
            Updated on 2014-03-25T02:48:09Z at 2014-03-25T02:48:09Z by iron-man
            • JRules
              JRules
              5 Posts
              ACCEPTED ANSWER

              Re: XSLT random number generation and assigning to a datapower context variable

              ‏2012-10-09T18:56:46Z  in response to HermannSW
              Thanks a bunch. Works just like I wanted :)
            • JRules
              JRules
              5 Posts
              ACCEPTED ANSWER

              Re: XSLT random number generation and assigning to a datapower context variable

              ‏2012-10-09T19:04:54Z  in response to HermannSW
              One last question, let's say I wanted only a 2 digit number in stead of 4 digits, what and where would I change in this code?
              • HermannSW
                HermannSW
                4357 Posts
                ACCEPTED ANSWER

                Re: XSLT random number generation and assigning to a datapower context variable

                ‏2012-10-09T19:34:59Z  in response to JRules
                format-number() seems not to be helpful here:
                $ echo "<foobar/>" | xpath++ "substring(format-number(0.0123456, '.####'),2)" -
                0123
                $ echo "<foobar/>" | xpath++ "substring(format-number(0.0123456, '.#####'),2)" -
                01235
                $
                


                 
                So here is the generalization for "$digits" digits:
                <xsl:stylesheet version="1.0"
                ...
                  xmlns:str="http://exslt.org/strings"
                >
                ...
                <xsl:variable name="digits" select="2"/>
                 
                <xsl:variable name="zeros" select="str:padding($digits - 1, '0')"/>
                <xsl:variable name="factor" select="concat('1', str:padding($digits, '0'))"/>
                 
                <Num>
                <xsl:variable name="scaled" select="floor($randNumb * $factor)"/>
                 
                <xsl:value-of select="concat(substring($zeros, string-length($scaled)), $scaled)"/>
                </Num>
                ...
                


                Hermann <myXsltBlog/> <myXsltTweets/>
                Updated on 2014-03-25T02:47:57Z at 2014-03-25T02:47:57Z by iron-man
                • JRules
                  JRules
                  5 Posts
                  ACCEPTED ANSWER

                  Re: XSLT random number generation and assigning to a datapower context variable

                  ‏2012-10-09T19:45:54Z  in response to HermannSW
                  Awesome! Works great... Thanks Hermann.
  • BalajiAllam
    BalajiAllam
    7 Posts
    ACCEPTED ANSWER

    Re: XSLT random number generation and assigning to a datapower context variable

    ‏2012-10-09T19:50:45Z  in response to BalajiAllam
    Thanks for everyone that helped!
    • Jrules80
      Jrules80
      80 Posts
      ACCEPTED ANSWER

      Re: XSLT random number generation and assigning to a datapower context variable

      ‏2012-10-10T03:49:50Z  in response to BalajiAllam
      Umm... so, does Math:random() function work across all DP appliances? Because, I executed this xslt code successfully at work that has the latest firmware (4.x) and at home I tried to execute the same code on a datapower box which is running on 3.7.3.7 (it is a XB150 box). Please advise~
      • HermannSW
        HermannSW
        4357 Posts
        ACCEPTED ANSWER

        Re: XSLT random number generation and assigning to a datapower context variable

        ‏2012-10-10T08:25:01Z  in response to Jrules80
        Hi,

        please see posting "EXSLT support in DataPower/Firefox/Xalan/xsltproc":
        https://www.ibm.com/developerworks/mydeveloperworks/blogs/HermannSW/entry/exslt_support_in_datapower_firefox_xalan_xsltproc12

        The EXSLT math module became completely implemented with DataPower 3.8.2 firmware.

        3.7.3 firmware went end EOS (End Of Service, see dates) last December, 3.8.0 went EOS last month and 3.8.1 will go EOS end of this year.
        So math:random() is available in all supported firmwares in 2013.

        OK, math:random() is supported in 3.8.2 DataPower firmware, but is not supported in 3.8.1 DataPower firmware.

        But Suresh (Liv2luv) pointed to a posting providing random numbers in DataPower firmware based of dp:random-bytes() in attached stylesheet sampleData.xsl:
        http://www.ibm.com/developerworks/forums/thread.jspa?messageID=14569358#14569358

        OK, find a implementation of "math:random()" for pre 3.8.2 firmwares here (stylesheet is attached, too).
        For better efficiency you should use "dp:random-sequence($n)" to create $n random values instead calling "math:random()" $n times:
        
        $ echo 
        "<foobar/>" | coproc2 math-random.xsl - http:
        //dp1-l3:2223 <Version>XI50.3.7.3.18</Version> 0.27372423838824034 <r>0.917497823946178</r><r>0.8108444742392749</r><r>0.9152125671971589</r> $ $ echo 
        "<foobar/>" | coproc2 math-random.xsl - http:
        //dp1-l3:2223 <Version>XI50.3.7.3.18</Version> 0.6555963535793126 <r>0.7959447687026113</r><r>0.8919260466936976</r><r>0.03579669306054711</r> $ $ echo 
        "<foobar/>" | coproc2 math-random.xsl - http:
        //dp1-l3:2223 <Version>XI50.3.7.3.18</Version> 0.7694448854308575 <r>0.49533103965222836</r><r>0.5587191139347851</r><r>0.41862683347426355</r> $ $ cat math-random.xsl <!-- demo of math:random() 
        
        for pre 3.8.2 DataPower firmwares --> <xsl:stylesheet version=
        "1.0" xmlns:xsl=
        "http://www.w3.org/1999/XSL/Transform" xmlns:dp=
        "http://www.datapower.com/extensions" xmlns:math=
        "http://exslt.org/math" xmlns:func=
        "http://exslt.org/functions" extension-element-prefixes=
        "dp" exclude-result-prefixes=
        "math" > <xsl:output omit-xml-declaration=
        "yes"/>   <xsl:template match=
        "/"> <xsl:copy-of select=
        "dp:variable('var://service/system/status/FirmwareVersion') /statistics/FirmwareVersion/Version
        "/> <xsl:text>
        </xsl:text>   <xsl:value-of select=
        "math:random()"/><xsl:text>
        </xsl:text> <xsl:copy-of select=
        "dp:random-sequence(3)"/> <xsl:text>
        </xsl:text> </xsl:template>   <!-- math:random() implementation 
        
        for pre 3.8.2 DataPower firmwares --> <func:function name=
        "math:random"> <func:result select=
        "dp:scale4(dp:random-bytes(4))" /> </func:function>   <!-- input:  base64 encoded 4 
        
        byte sequence (eg. by 
        "dp:random-bytes(4)") 
        
        return: value between 0 and 1 represented by input --> <func:function name=
        "dp:scale4"> <xsl:param name=
        "bytes4"/>   <func:result select=
        "dp:radix-convert($bytes4,64,10) div 4294967296" /> </func:function>   <!-- Recursively create sequence of random values --> <func:function name=
        "dp:random-sequenceR"> <xsl:param name=
        "bytes"/>   <xsl:variable name=
        "junk"> <xsl:message dp:priority=
        "information">bytes(<xsl:value-of select=
        "$bytes"/>)</xsl:message> </xsl:variable>   <func:result> <xsl:
        
        if test=
        "$bytes != ''"> <r><xsl:value-of select=
        "dp:scale4(dp:substring-base64($bytes,1,4))"/></r>   <xsl:copy-of select=
        "dp:random-sequenceR(dp:substring-base64($bytes,5,string-length($bytes)))"/> </xsl:if> </func:result> </func:function>   <!-- input:  number of requested random values between 0 and 1 
        
        return: requested 
        "sequence" DP does not support XPath 2.0 sequences. So 
        
        return <r>num1</r><r>num2</r>... --> <func:function name=
        "dp:random-sequence"> <xsl:param name=
        "numberOfItems"/>   <xsl:variable name=
        "bytes" select=
        "dp:random-bytes(4*$numberOfItems)"/>   <func:result select=
        "dp:random-sequenceR($bytes)" /> </func:function>       </xsl:stylesheet> $
        


         
        Hermann<myXsltBlog/> <myXsltTweets/>
        • Jrules80
          Jrules80
          80 Posts
          ACCEPTED ANSWER

          Re: XSLT random number generation and assigning to a datapower context variable

          ‏2012-10-10T14:50:17Z  in response to HermannSW
          Hermann, so here is the output that I am getting:
          <Version>XI50.3.7.3.7</Version>
          <r>0.5910149551928043</r>
          <r>0.7159211533144116</r>
          <r>0.35461692977696657</r>
          I only need one random number and it would help if I got a 4 digit number (or better yet, if there was a way I could change the value to select if I wanted 2 digits or 3 or more)

          Due to lack of my understanding, is there any way you could make the code simpler? :). I'd really appreciate if this new code for 3.7 is in line with one for 3.82 (and later. See attached file)
          • HermannSW
            HermannSW
            4357 Posts
            ACCEPTED ANSWER

            Re: XSLT random number generation and assigning to a datapower context variable

            ‏2012-10-10T16:41:52Z  in response to Jrules80
            OK, find attached your stylesheet added with the minimal stuff needed to get it working on 3.7.3 firmware.
            I could not resist to add at least a comment with the firmware information in the output ;-)

            
            $ echo 
            "<foobar/>" | coproc2 RandomNumb.2.xsl - http:
            //dp1-l3:2223 -s | tidy -q -xml <soapenv:Envelope xmlns:bac=
            "http://www.example.org/Backend1/" xmlns:soapenv=
            "http://schemas.xmlsoap.org/soap/envelope/" xmlns:str=
            "http://exslt.org/strings" xmlns:func=
            "http://exslt.org/functions"> <soapenv:Header /> <soapenv:Body> <bac:Response> <!--XI50.3.7.3.18--> <Num>51</Num> </bac:Response> </soapenv:Body> </soapenv:Envelope>   $ echo 
            "<foobar/>" | coproc2 RandomNumb.2.xsl - http:
            //dp1-l3:2223 -s | tidy -q -xml <soapenv:Envelope xmlns:bac=
            "http://www.example.org/Backend1/" xmlns:soapenv=
            "http://schemas.xmlsoap.org/soap/envelope/" xmlns:str=
            "http://exslt.org/strings" xmlns:func=
            "http://exslt.org/functions"> <soapenv:Header /> <soapenv:Body> <bac:Response> <!--XI50.3.7.3.18--> <Num>69</Num> </bac:Response> </soapenv:Body> </soapenv:Envelope>   $
            


             
            Hermann<myXsltBlog/> <myXsltTweets/>
            • Jrules80
              Jrules80
              80 Posts
              ACCEPTED ANSWER

              Re: XSLT random number generation and assigning to a datapower context variable

              ‏2012-10-10T20:22:05Z  in response to HermannSW
              Thank you :)