3

I need to choose random item from my XML by XSLT. I have such XML:

<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <item>
      <title>Nr. 19/2015</title>
      <link>http://ugeskriftet.dk/blad/9-2016</link>
      <description>Link og billed til det sidste nye Ugeskrift for Læger</description>
      <image>
        <url>http://orlovka.org.ru/biblioznajka/images/stories/pic6/01.png</url>
      </image>
    </item> 
    <item>
      <title>Nr. 9/2016</title>
      <link>http://ugeskriftet.dk/blad/9-2016</link>
      <description>Bald - who are they are?</description>
      <image>
        <url>http://www.moscowbooks.ru/image/book2/313/big/i313969.jpg</url>
      </image>
    </item>
    <item>
      <title>Nr. 3/2014</title>
      <link>http://ugeskriftet.dk/blad/9-2016</link>
      <description>How to tell your shildren</description>
      <image>
        <url>http://www.zipsites.ru/me/literatura/Yuliya_Doppenganger_Kak_obyasnit_rebyonku_chto_Vy_sobiraetes/cover.jpg</url>
      </image>
    </item>
  </channel>
</rss>

I need choose random item from this file by XSLT. My XSLT looks like this:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:sc="http://www.sitecore.net/sc"
    xmlns:dot="http://www.sitecore.net/dot"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsh="http://www.matchwork.com/xsh"
    exclude-result-prefixes="sc dot xsi xsh">

   <!-- parameters -->
  <xsl:param name="lang" select="'en'"/>
  <xsl:param name="id" select="''"/>
  <xsl:param name="sc_item"/>
  <xsl:param name="sc_currentitem"/>
  <xsl:param name="jobId" select="sc:qs('id')"/>

  <xsl:output method="xml" indent="yes" encoding="utf-8" omit-xml-declaration="yes" />

  <xsl:template match="/">
      <div class="ReadingContainer">
          <div class="LiTitle">
            <xsl:call-template name="OutputSitecoreField">
              <xsl:with-param name="root" select="$sc_currentitem"/>
              <xsl:with-param name="fieldName" select="'RSS Title'"/>
            </xsl:call-template>
          </div>
          <div class="ReadingList">
            <xsl:for-each select="rss/channel/item">

              <xsl:if test="position() &lt;= 2">
                  <div class="ReadingItemContainer">
                    <div class="ReadingImgContainer">
                      <a class="ReadingUrl" target="_blank">
                          <xsl:attribute name="href">
                              <xsl:value-of select="link"/>
                          </xsl:attribute>
                          <img alt="book">
                              <xsl:attribute name="src">
                                  <xsl:value-of select="url"/>
                              </xsl:attribute>
                          </img>
                      </a>
                    </div>
                    <div class="ReadingDescriptionContainer">
                        <p class="ReadingDate">
                            <xsl:value-of select="title"/>
                        </p>
                        <p class="ReadingDescription">
                            <xsl:value-of select="description"/>
                        </p>
                    </div>
                  </div>
              </xsl:if>

            </xsl:for-each>
          </div>
      </div>
   </xsl:template>

  <!-- Render text field from Sitecore -->
  <xsl:template name="OutputSitecoreField">
    <xsl:param name="root" select="''"/>
    <xsl:param name="fieldName" select="''"/>

    <xsl:if test="$fieldName != ''">
      <xsl:value-of select="sc:fld($fieldName,$root)"/>
    </xsl:if>
  </xsl:template>


  <xsl:template name="removeHtmlTags">
    <xsl:param name="html"/>

    <xsl:choose>
      <xsl:when test="contains($html, '&lt;')">
        <xsl:value-of select="substring-before($html, '&lt;')"/>
        <!-- Recurse through HTML -->
        <xsl:call-template name="removeHtmlTags">
          <xsl:with-param name="html" select="substring-after($html, '&gt;')"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$html"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

How i can show random item every time user is going on the page? Sorry for so much code, i am not sure in usefulness some part of the code, so i decided to keep all code. Thanks you

mr__brainwash
  • 1,334
  • 3
  • 16
  • 40
  • Well, how do you apply the XSLT to the XML? Is that using a programming language like C# where you have access to some random number generation API? – Martin Honnen May 16 '16 at 14:20
  • Yes,there is using C#,but i don't have access to c# code.Is there some way count total number of items and generate random int between 0 and length of items? – mr__brainwash May 16 '16 at 14:29
  • 1
    XSLT 3.0 has random number generation http://saxonica.com/html/documentation/functions/fn/random-number-generator.htm so using the commercial editions of Saxon 9.7 .NET would allow it inside of your XSLT code. And .NET and C# can do that too so check whether you can use an extension function or object with your XSLT processor. Otherwise you will need to check whether you can use http://fxsl.sourceforge.net/articles/Random/Casting%20the%20Dice%20with%20FXSL-htm.htm. – Martin Honnen May 16 '16 at 15:32
  • @ДенисЯломист See: http://stackoverflow.com/questions/25867727/generate-random-number-in-rss-viewer-webpart/25869149#25869149 – michael.hor257k May 16 '16 at 17:18

2 Answers2

0

How i can show random item every time user is going on the page?

This is not possible if you are using only XSLT 1.0 or 2.0, without some external input that would change every time the transformation is performed.

I did not think it would be necessary to state such an obvious fact: any XSL transformation is a deterministic algorithm. Given a particular input, it will always produce the same output.

If the page is the same every time, then the "random" item you choose will also be the same every time. You must provide an additional "seed" that will not be the same every time (for example, the current time), if you want this to work.


BTW, if you do manage to get the current time, you can use simply:

floor ( $seconds * $count-items / 60 ) + 1

to determine the number of item to select.

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • This answer is misleading the reader to believe that no standard way exists in XSLT 2.0 for obtaining the current date / time / dateTime. Voted down by me. – Dimitre Novatchev May 17 '16 at 04:17
-1

I would recommend reading this:

Casting the Dice with FXSL: Random Number Generation Functions in XSLT

This is a paper I wrote more than 14 years ago. It discusses the functionality provided by the FXSL library for functional programming with XSLT, for generating random numbers, random sequences, random indexes, sequences whose items obey a given probabilistic distribution, etc.

The top-level TOC looks like this:

  1. Generation of a single random number and a sequence of random numbers. Scaling a sequence.
  2. Generating a random sequence following a distribution. Subsequences.
  3. Testing randomness with Monte Carlo integration

In the XSLT 2.0 edition of FXSL no extension function is necessary -- to get a seed for generating a random sequence (or random number) one can use a standard XPath 2.0 function, such as: current-dateTime() or current-time()

In the XSLT 1.0 edition of FXSL the xxx:node-set() may be needed. Also, in XSLT 1.0 one needs to provide a seed, that has to be either passed as parameter (such as the seconds in the current time, or the number of seconds elapsed since some dateTime), or use an extension function, that will provide the same.

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
  • For anyone tempted to actually read this, I suggest starting in the middle of section #2, where it says: "*Finally, someone will rightfully ask **why our random sequences are always the same**, starting with exactly the same numbers. A workaround for this issue is to be able to pick up a subsequence of the random sequence, and define the starting element of the subsequence in some non-deterministic way (e.g. **use an extension function to get the current time** and use the value of the seconds as index for the start of the subsequence).*" (emphasis added by me). – michael.hor257k May 17 '16 at 03:37
  • @michael.hor257k, This article was written when there was no XSLT 2.0. I edited the answer to include the fact that the XSLT 1.0 edition of FXSL needs some way of providing a seed. This can be passed as parameter to the transformation, in which case no extension function is necessary. In XSLT 2.0 no extension function is required, because one can use one of the three standard XPath 2.0 functions that provide the current date / time /dateTime – Dimitre Novatchev May 17 '16 at 04:36