Copied to clipboard

Flag this post as spam?

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


  • Shaun 248 posts 475 karma points
    Apr 16, 2010 @ 00:19
    Shaun
    0

    Tricky XSLT question

    I need to generate some xslt that will loop through all nodes of a particular nodetypealias, in order to sort them into an order based on a property of the nodetype.

    each node has a "votes" property and I need to see what the ranking of a particular node is, e.g.

    node 1 - 1000 votes - rank 1

    node 2 - 1000 votes - rank 1 (it share's the winning number of votes)

    node 3 - 300 votes - rank 2

    node 4 - 200 votes - rank3 etc etc.

    in sloppy-pseudocode I think the xslt should look something like this.

    $count = 1
    <xsl:for-each select="umbraco.library:GetXmlNodeById($source)/node [string(data [@alias='umbracoNaviHide']) != '1'>
        <xsl:sort by property"votes"> 
        if(thisisfirstnode)
        {
            $votes = votes property of node 1
    
        }
        if(vote property of current node < $votes)
        {
            $count++;
        }
        if(currentnode id = "x")
        {
            break out of for each loop.
        }   
    
    </xsl:for-each>
    
    do something interesting with the current value of $count

    But is any of this possible in xslt? I know amending the variable isn't possible, do I have to use a seperate template containing some recursion, and can anyone point me to a simple example of this type of recursion in xslt?

    Many thanks

  • Chriztian Steinmeier 2726 posts 8320 karma points MVP 4x admin c-trib
    Apr 16, 2010 @ 01:31
    Chriztian Steinmeier
    2

    Hi Shaun,

    Without understanding your scenario completely, here's a way to get the final value of $count:

    <xsl:variable name="sourceNode" select="umbraco.library:GetXmlNodeById($source)" />
    
    <xsl:for-each select="$sourceNode/node[not(data[@alias = 'umbracoNaviHide']) = 1]">
        <xsl:sort select="data[@alias = 'votes']" data-type="number" order="descending" />
        <xsl:if test="position() = 1">
            <!-- Output number of nodes with a votes value less than the top voted -->
            <xsl:value-of select="count(../node[data[@alias = 'votes'] &lt; current()/data[@alias = 'votes']])" />
        </xsl:if>
    </xsl:for-each>

    /Chriztian

     

  • Chriztian Steinmeier 2726 posts 8320 karma points MVP 4x admin c-trib
    Apr 16, 2010 @ 02:03
    Chriztian Steinmeier
    5

    Hi again - I thought about it some more and came up with this, which will list all the nodes sorted by rank, descending - so you can see how to take that value when rendering a particular node (for CSS maybe?):

     <!-- Grab reference to the parent node -->
        <xsl:variable name="sourceNode" select="umbraco.library:GetXmlNodeById($source)" />
    
        <xsl:template match="/">
          <!-- Grab the top voted node --> 
            <xsl:variable name="topNode" select="$sourceNode/node[not(../node/data[@alias = 'votes'] &gt; data[@alias = 'votes'] )]" />
    
            <p>
                Top voted: <strong><xsl:value-of select="$topNode/@nodeName" /></strong> with
                <xsl:value-of select="$topNode/data[@alias = 'votes']" /> votes!
            </p>
            <p>
                Number of nodes with a value less than the top voted:
                <xsl:value-of select="count($sourceNode/node[data[@alias = 'votes'] &lt; $topNode/data[@alias = 'votes']])" />
            </p>
    
            <!-- List all nodes sorted by rank -->
            <xsl:apply-templates select="$sourceNode/node">
                <xsl:sort select="count(../node[data[@alias = 'votes'] &lt; current()/data[@alias = 'votes']])" data-type="number" order="descending" />
            </xsl:apply-templates>
    
        </xsl:template>
    
        <!-- Output for each individual node -->
        <xsl:template match="node">
            <xsl:variable name="myVotes" select="data[@alias = 'votes']" />
            <div>
                <p>
                    Node: <xsl:value-of select="@nodeName" /> -
                    Rank: <xsl:value-of select="count(../node[data[@alias = 'votes'] &lt; $myVotes])" />
                </p>
            </div>
        </xsl:template>
    
        <!-- No output for these -->
        <xsl:template match="node[data[@alias = 'umbracoNaviHide'] = 1]" />
    
    

    /Chriztian

  • Shaun 248 posts 475 karma points
    Apr 16, 2010 @ 12:37
    Shaun
    0

    Wow! thats wonderful Chriztian! I didn't expect a complete bit of xslt, I thought i'd get a link to a example of something using similar methods. Thank you very very much for this, you're a star!

  • Chriztian Steinmeier 2726 posts 8320 karma points MVP 4x admin c-trib
    Apr 16, 2010 @ 13:13
    Chriztian Steinmeier
    0

    Thanks Shaun,

    Thing is -- I have CXA ("Compulsory XSLT Addiction" :-)

    /Chriztian

  • Laurence Gillian 597 posts 1214 karma points
    Apr 16, 2010 @ 13:23
    Laurence Gillian
    0

    Chriztian destroyed another XSLT problem! Sweet solution! Kudos! /Lx

  • 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