Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Bjarne Fyrstenborg 1182 posts 3441 karma points MVP 4x c-trib
    Dec 05, 2012 @ 00:59
    Bjarne Fyrstenborg
    0

    Get random node of the ones picked with MNTP

    Hi..

    I have some quotes listed in my content structure..

    On each page I want to pick the nodes which should appear on the current page.. but of the nodes picked with multi-node tree picker a random of the selected quotes should be displayed.

    <?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.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" xmlns:PS.XSLTsearch="urn:PS.XSLTsearch" 
        exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets PS.XSLTsearch ">
    
    
      <xsl:output method="xml" omit-xml-declaration="yes"/>
    
      <xsl:param name="currentPage"/>
      <xsl:variable name="boxIds" select="$currentPage/self::*[normalize-space(boxes)][1]/boxes//nodeId" />
    
      <xsl:variable name="random" select="floor(Exslt.ExsltMath:random() * count($boxIds)) + 1"/>
    
      <xsl:template match="/">
          <xsl:if test="normalize-space($boxIds)"> 
            <xsl:for-each select="$boxIds">
                <xsl:variable name="box" select="umbraco.library:GetXmlNodeById(.)" />
                <xsl:apply-templates select="$box" />
            </xsl:for-each>
          </xsl:if>
      </xsl:template>
    
      <xsl:template match="Quote">
          <xsl:variable name="qSize" select="quoteTextSize" />
          <xsl:variable name="textSize">
            <xsl:value-of select="Exslt.ExsltStrings:lowercase($qSize)"/>
          </xsl:variable>
    
          <xsl:variable name="qClass">
          <xsl:choose>
            <xsl:when test="$textSize = 'small' or $textSize = ''">
                <xsl:value-of select="'smallText'"/>
            </xsl:when>
            <xsl:when test="$textSize = 'medium'">
                <xsl:value-of select="'mediumText'"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="'largeText'"/>
            </xsl:otherwise>
          </xsl:choose>
          </xsl:variable>
    
          <section>
                <xsl:attribute name="class">
                    <xsl:text>quoteBox </xsl:text>
                    <xsl:value-of select="$qClass"/>
                </xsl:attribute>
                <p class="quoteText">
                    <xsl:if test="quoteText != ''">
                        <xsl:value-of select="concat('&quot;', umbraco.library:ReplaceLineBreaks(quoteText), '&quot;')" disable-output-escaping="yes"/>
                    </xsl:if>
                </p>
                <p class="quoteName"><xsl:value-of select="umbraco.library:ReplaceLineBreaks(quoteName)" disable-output-escaping="yes"/></p>
          </section>
    
      </xsl:template>
    
    </xsl:stylesheet>

    How can I set the random Quote node of the selected in the apply-templates?

    /Bjarne

  • Chriztian Steinmeier 2726 posts 8320 karma points MVP 4x admin c-trib
    Dec 05, 2012 @ 08:43
    Chriztian Steinmeier
    0

    Hi Bjarne,

    Here's a way to do that:

    <xsl:template match="/">
        <!-- Pick a random box index -->
        <xsl:variable name="random" select="floor(Exslt.ExsltMath:random() * count($boxIds)) + 1"/>
    
        <!-- Process the one - this gets us into the Umbraco XML doc -->
        <xsl:apply-templates select="$boxIds[position() = $random]" />
    </xsl:template>
    
    <!-- Simple 'redirect' to the referenced node -->
    <xsl:template match="nodeId">
        <!-- id() works because we are now inside the Umbraco XML -->
        <xsl:apply-templates select="id(.)" />
    </xsl:template>
    
    <!-- Template for the Quote -->
    <xsl:template match="Quote">
        <!-- Do something -->
    </xsl:template>

     

    The difference between id() and GetXmlNodeById() is that id() will return an empty set if the picked node has been deleted (it's also a native XPath function), where GetXmlNodeById() will return an error node (or something) that you will then need to error check.

    The tricky part is that id() will only find a node inside the document that contains the current context node - a concept that's also hard to explain in Umbraco's specific environment - I tried here: https://gist.github.com/871656

    So by applying templates for the randomly selected <nodeId> element, we get "into" the Umbraco XML and from there can just use the id() function and not worry about error messages for deleted nodes.

    I know it's a completely different way of thinking, in terms of what most people are used to, but using XSLT it just makes so much more sense.

     

    /Chriztian

  • Bjarne Fyrstenborg 1182 posts 3441 karma points MVP 4x c-trib
    Dec 05, 2012 @ 13:10
    Bjarne Fyrstenborg
    0

    Hi Chriztian

    Thanks, it seems to do it :)

    I have done something similar before, but where I just get a random node of a nodeset.

    <xsl:param name="currentPage"/>
            <xsl:variable name="random" select="floor(emath:random() * count($currentPage/ancestor-or-self::root/descendant-or-self::Quote)) + 1"/>

            <xsl:template match="/">
             <xsl:apply-templates select="$currentPage/ancestor-or-self::root/descendant-or-self::Quote[$random]" />
            </xsl:template>

            <xsl:template match="Quote">
                    <div id="randquote">
                            <xsl:apply-templates select="quoteText[normalize-space()]" />
                            <xsl:apply-templates select="quoteName[normalize-space()]" />
                    </div>
            </xsl:template>
            
            <xsl:template match="quoteText">
                    <class="quoteText">
                            <xsl:value-of select="." />
                      <span class="quote_end"><xsl:text</xsl:text></span>
                    </p>
                    
            </xsl:template>
              
            <xsl:template match="quoteName">
                    <class="name">
                            <xsl:value-of select="." />
                    </p>
            </xsl:template>

     

    So what you get from the code above is a random node id and from that get the xml?

    This is the code I ended up with:

    <xsl:param name="currentPage"/>
      <xsl:variable name="boxIds" select="$currentPage/self::*[normalize-space(boxes)][1]/boxes//nodeId" />
      <!-- Replace 'article' with the wanted document -->
      <xsl:variable name="random" select="floor(Exslt.ExsltMath:random() * count($boxIds)) + 1"/>
    
      <xsl:template match="/">
          <!-- Pick a random box index -->
          <xsl:variable name="random" select="floor(Exslt.ExsltMath:random() * count($boxIds)) + 1"/>
    
          <!-- Process the one - this gets us into the Umbraco XML doc -->
          <xsl:apply-templates select="$boxIds[position() = $random]" />
      </xsl:template>
    
      <!-- Simple 'redirect' to the referenced node -->
      <xsl:template match="nodeId">
            <!-- id() works because we are now inside the Umbraco XML -->
            <xsl:apply-templates select="id(.)" />
      </xsl:template>
    
      <xsl:template match="Quote">
          <xsl:variable name="qSize" select="quoteTextSize" />
          <xsl:variable name="textSize">
            <xsl:value-of select="Exslt.ExsltStrings:lowercase($qSize)"/>
          </xsl:variable>
    
          <xsl:variable name="qClass">
          <xsl:choose>
            <xsl:when test="$textSize = 'small' or $textSize = ''">
                <xsl:value-of select="'smallText'"/>
            </xsl:when>
            <xsl:when test="$textSize = 'medium'">
                <xsl:value-of select="'mediumText'"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="'largeText'"/>
            </xsl:otherwise>
          </xsl:choose>
          </xsl:variable>
    
          <section>
                <xsl:attribute name="class">
                    <xsl:text>quoteBox </xsl:text>
                    <xsl:value-of select="$qClass"/>
                </xsl:attribute>
                <p class="quoteText">
                    <xsl:if test="quoteText != ''">
                        <xsl:value-of select="concat('&quot;', umbraco.library:ReplaceLineBreaks(quoteText), '&quot;')" disable-output-escaping="yes"/>
                    </xsl:if>
                </p>
                <p class="quoteName"><xsl:value-of select="umbraco.library:ReplaceLineBreaks(quoteName)" disable-output-escaping="yes"/></p>
          </section>
    
      </xsl:template>

    /Bjarne

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies