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 2800 posts 8790 karma points MVP 8x 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 2800 posts 8790 karma points MVP 8x 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 2800 posts 8790 karma points MVP 8x admin c-trib
    Apr 16, 2010 @ 13:13
    Chriztian Steinmeier
    0

    Thanks Shaun,

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

    /Chriztian

  • Laurence Gillian 600 posts 1219 karma points
    Apr 16, 2010 @ 13:23
    Laurence Gillian
    0

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

Please Sign in or register to post replies

Write your reply to:

Draft