Copied to clipboard

Flag this post as spam?

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


  • jacob phillips 130 posts 372 karma points
    Aug 12, 2014 @ 02:36
    jacob phillips
    0

    prev/next + sort + msxml:node-set

    Hi,

    I'm trying to combine the xslt approaches used in this post and this post, to print out prev/next links (but if I'm on the first item, not prev, and if I'm on the last, no next).

    The docType structure has "Program" docTypes and underneath those, there are 3 levels of docType 'systemDateFolder' (year->month->day), and finally at the leaf level, "show" docType. I want prev/next on my show items.

    The default ordering of the nodes seems to be by createDate, but I am running into instances where this is causing problems. So I need to sort on 'displayDate'. I'm most familiar with sorting inside for-loops like this:

    <xsl:sort select="umbraco.library:FormatDateTime(displayDate, 'yyyyMMddHHmm')" data-type="number" order="descending" /> 
    

    But I have eventually found that I cannot sort my set like this when using msxml:nodeset.

    So I kind of have it working using the way I would normally do it, but I want to make it closer to the examples in the links above:

    <xsl:output method="xml" omit-xml-declaration="yes"/>
    
    <xsl:param name="currentPage"/>
    
        <!-- root comprising node set --> 
        <xsl:variable name="programRoot" select="$currentPage/ancestor-or-self::cprProgramItem" />
    
        <!-- Create a special collection of nodes for paging -->
        <xsl:variable name="data" select="msxml:node-set($programRoot/systemDateFolder/systemDateFolder/systemDateFolder/show)" />
    
    
    <xsl:template match="/">
    
    <xsl:variable name="p">
    <xsl:for-each select="$data">
    <xsl:if test="$currentPage/@id = ./@id">
    <xsl:value-of select="position()" />
    </xsl:if>
    </xsl:for-each>
    </xsl:variable>
    
    
            <xsl:variable name="prevNodeId">
                <xsl:choose>
                    <xsl:when test="$currentPage/@id = $data[1]/@id">
                <xsl:value-of select="'0'"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="$data[$p - 1]/@id" />
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
    
            <xsl:variable name="nextNodeId">
                <xsl:choose>
                    <xsl:when test="$currentPage/@id = $data[last()]/@id">
                <xsl:value-of select="'0'"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="$data[$p + 1]/@id" />
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
    
    
    
    
    <xsl:if test="$prevNodeId != '0'">
    <h3 style="background-color:#e4e1e0;padding:.5em .7em;float:left;display:inline;border: 1px solid #ccc;">
    <a>
    <xsl:attribute name="href">
    <xsl:value-of select="umbraco.library:NiceUrl($prevNodeId)" />
    </xsl:attribute> OLDER SHOW
    </a>
    </h3>
    </xsl:if>
    
    <xsl:if test="$nextNodeId != '0'">
    <h3 style="background-color:#e4e1e0;padding:.5em .7em;float:right;display:inline;border: 1px solid #ccc;">
    <a>
    <xsl:attribute name="href">
    <xsl:value-of select="umbraco.library:NiceUrl($nextNodeId)" />
    </xsl:attribute>NEWER SHOW
    </a>
    </h3>
    </xsl:if>
    
    
    </xsl:template>
    

    I would really like to try and not use loops, and use apply-templates, but I'm getting stuck in a couple of places. Here's what I've got:

        <xsl:output method="xml" omit-xml-declaration="yes"/>
    
    <xsl:param name="currentPage"/>
    
        <!-- get the parent program root for this show i'm on --> 
        <xsl:variable name="programRoot" select="$currentPage/ancestor-or-self::cprProgramItem" />
    
        <!-- Use that root to get all the shows. 1) I need to figure out how to sort this using apply-templates I think -->
        <xsl:variable name="data" select="msxml:node-set($programRoot/systemDateFolder/systemDateFolder/systemDateFolder/show)" />
    
    
    
    
    
    <xsl:template match="/">
    <xsl:apply-templates select="$currentPage" />
    </xsl:template>
    
    <!-- 2) 'node' here is part of the old schema? I change it to 'show' because those are the alias of the leaves I want to match --> 
        <xsl:template match="show">
    
           <!-- Find the equivalent of position() but within our special collection -->
    <!-- 3) This appears to give me the absolute position of this node in the entire content tree? It's like 2603 on the first item  and there's only 
    a couple of hundred of 'shows' in this program. Obviously, I can't use this '$p' to position links from $data. I created a for loop here in order 
        to look up what my currentPage/@id position is inside $data, but I should just get the select syntax right I think? I want to not use loops. 
    --> 
    
            <xsl:variable name="p">
                <xsl:number level="any" count="show" />
            </xsl:variable>
    
    <!-- 
        <xsl:variable name="p">
        <xsl:for-each select="$data">
        <xsl:if test="$currentPage/@id = ./@id">
        <xsl:value-of select="position()" />
        </xsl:if>
        </xsl:for-each>
        </xsl:variable>
    --> 
    
            <xsl:variable name="prevNodeId">
                <xsl:choose>
                    <xsl:when test="$currentPage/@id = $data[1]/@id">
                <xsl:value-of select="'0'"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="$data[$p - 1]/@id" />
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
    
            <xsl:variable name="nextNodeId">
                <xsl:choose>
                    <xsl:when test="$currentPage/@id = $data[last()]/@id">
                <xsl:value-of select="'0'"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="$data[$p + 1]/@id" />
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
    
    
    <xsl:if test="$prevNodeId != '0'">
    <h3 style="background-color:#e4e1e0;padding:.5em .7em;float:left;display:inline;border: 1px solid #ccc;">
    <a>
    <xsl:attribute name="href">
    <xsl:value-of select="umbraco.library:NiceUrl($prevNodeId)" />
    </xsl:attribute> OLDER SHOW
    </a>
    </h3>
    </xsl:if>
    
    <xsl:if test="$nextNodeId != '0'">
    <h3 style="background-color:#e4e1e0;padding:.5em .7em;float:right;display:inline;border: 1px solid #ccc;">
    <a>
    <xsl:attribute name="href">
    <xsl:value-of select="umbraco.library:NiceUrl($nextNodeId)" />
    </xsl:attribute>NEWER SHOW
    </a>
    </h3>
    </xsl:if>
    
    
    
    
    
    
    
    <textarea>
    p:<xsl:value-of select="$p" />
    currentPage/id:<xsl:value-of select="$currentPage/@id" />
    prevNodeId:<xsl:value-of select="$prevNodeId" />
    nextNodeId:<xsl:value-of select="$nextNodeId" />
    </textarea>
    
    </xsl:template>
    

    So my questions are in the xslt, but basically:

    1) How do I sort $data with another apply-templates while still being able to match to the other apply-templates? 2) When I go to find my position in data in a template match, the old schema example was 'node[@nodeTypeAlias = $groupType]/node'

    I tried systemDateFolder/show, systemDateFolder/systemDateFolder/systemDateFolder/show, and other variations, but I think I'm not understanding the context of what I'm trying to select with the count variable:

       <xsl:number level="any" count="node[@nodeTypeAlias = $groupType]/node" />
    

    3) I guess if I can figure out 2), three really works itself out.

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Aug 12, 2014 @ 09:40
    Chriztian Steinmeier
    0

    Hi Jacob,

    It sounds like you could try my Pagination Helper — even if you're only showing 1 result per page, and you don't want to show individual page links.

    It was designed to take all the calculation logic out of this typical problem, and just let you focus on having a template for the output.

    Maybe worth a shot?

    /Chriztian

    PS: Here's a direct link to the helper file in the dist directory, just in case :)

  • jacob phillips 130 posts 372 karma points
    Aug 18, 2014 @ 20:53
    jacob phillips
    0

    Thanks Chriztian,

    I got what I had working, I had to move on from this quickly.

    I'll keep this in mind in the future.

Please Sign in or register to post replies

Write your reply to:

Draft