views:

766

answers:

3

Hi all

I have a question about some sort af random function in XSLT.

I have an XML-file that very simplified look similar to this:

<node id="1198">
  <node id="1201">
    <data alias="name">Flemming</data>
    <data alias="picture">1200</data>
  </node>
  <node id="1207">
    <data alias="name">John</data>
    <data alias="picture">1205</data>
  </node>
  <node id="1208">
    <data alias="name">Michael</data>
    <data alias="picture">1206</data>
  </node>
</node>

I would like to have some XSLT, that ramdomly took one of the nodes id's and put it into a variable called "choosenNode". Like this, if the node with the ID of 1207 was the selected one:

<xsl:variable name="choosenNode" value="1207" />

How can i do this? Is there a random-function in XSLT? By the way, I would like the variable to be refreshed on every page where the XSLT is included.

And I work in Umbraco CMS, if that helps you guys.

Thanks, -Kim

A: 

Getting random number in xslt is not an easy task.

There's something that can do it but you probably has to provide seed for random generator http://fxsl.sourceforge.net/articles/Random/Casting%20the%20Dice%20with%20FXSL-htm.htm

Maybe the processor you are using to do xsl transformation has ability to extend xsl expressions with outside functions. In that case maybe you can use outside random function.

Kamil Szot
Umbraco has access to its own library of extension functions and the Microsoft ones inside the XSLT processor, so that problem is solved. Though scripting inside the XSLT processor can hammer the server
Chris S
A: 

All you need is a random number generator. There is none in XSLT thus the random number must be provided by something outside of XSLT. You will need to call a method from an external library to do this and the implemention of this library will depend on if you're on Windows (.NET or WIN32) or Linux and the XSLT processor. XSLT can do math but it lacks a lot of date/time related functions which happens to include a random number generator.

However, XSLT does have a XPath function called generate-id() which will generate an unique ID. If you could transform this to a nuimber somehow, it might be used to create a random number, although it would be predictable and some numbers might occur more often than others. I wouldn't use it.

If you use MSXSL to process your stylesheet then you can include JavaScript to generate random numbers within the stylesheet. (Or C# script when using .NET.)

Getting the node itself is easy, once you know the number of child nodes. Just ask for the node at the random position. Something like /node/node[5] would return the 5th node.

Workshop Alex
+3  A: 

In Umbraco you can do something like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:Stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
<xsl:stylesheet 
version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath"
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltMath">

<xsl:output method="xml" omit-xml-declaration="yes"/>

<xsl:param name="currentPage"/>

<!-- This should probably be a macro parameter so you can use this elsewhere-->
<xsl:variable name="parentNode" select="1048"/>

<xsl:template match="/">

        <xsl:variable name="numberOfNodes" select="count(umbraco.library:GetXmlNodeById($parentNode)/node)"/>

        <xsl:variable name="randomPosition" select="floor(Exslt.ExsltMath:random() * $numberOfNodes) + 1"/>

        <xsl:variable name="randomNode" select="umbraco.library:GetXmlNodeById($parentNode)/node [position() = $randomPosition]"/>

        <!--
          You now have the node in the $randomNode variable
          If you just want the id then you can do an XPath query on the variable
          or you can modify the XPath above to get the property you are after rather than
          the whole node
        -->

    <xsl:value-of select="$randomNode/@nodeName" />

</xsl:template>
</xsl:stylesheet>

Hope this helps.

Tim

Tim Saunders
That looks pretty cool Tim, this might be a good solution. I'll check it out tomorrow, so you'll get a correct answer there if it works :DThanks...
Kim Andersen
OK - I've not actually checked the code - just typed it pretty much off the top of my head, so beware bugs!
Tim Saunders
OOOPS - a few little typos in there. I've tidied it up and checked that it works in one of my Umbraco installations. I've also added a line showing how to grab a value.
Tim Saunders
This is perfect Tim!Thank you very much :)
Kim Andersen