Copied to clipboard

Flag this post as spam?

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


  • Connie DeCinko 931 posts 1159 karma points
    Feb 08, 2012 @ 19:23
    Connie DeCinko
    0

    Grouping and pagination

    I have a list I successfully display grouped by year and month. Now the list is getting huge. I need to paginate the results. I've looked at the examples but none combine the two. How would I take the code below and convert it to support pagination?

     

    <?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:Designit.VideoEmbed="urn:Designit.VideoEmbed" 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="html" omit-xml-declaration="yes"/>

    <xsl:param name="currentPage"/>

    <xsl:param name="previewWidth" select="16" />
    <xsl:param name="previewHeight" select="16" />
    <xsl:param name="videoWidth" select="640" />
    <xsl:param name="videoHeight" select="480" />

    <xsl:key name="years" match="* [@isDoc and (name()='LegalNewsHeadline' or name()='ArizonaAttorneyNewsCenterArticle')]" use="umbraco.library:FormatDateTime(publicationDate, 'yyyy')"/>
    <xsl:key name="months" match="* [@isDoc and (name()='LegalNewsHeadline' or name()='ArizonaAttorneyNewsCenterArticle')]" use="umbraco.library:FormatDateTime(publicationDate, 'yyyyMMMM')"/>

    <xsl:template match="/">

    <xsl:value-of select="umbraco.library:RegisterJavaScriptFile('fancybox', '/scripts/Designit.VideoEmbed/jquery.fancybox-1.3.1.pack.js')"/>
    <xsl:value-of select="umbraco.library:RegisterStyleSheetFile('cssFancyBox', '/css/Designit.VideoEmbed/jquery.fancybox-1.3.1.css')"/>

    <xsl:for-each select="$currentPage/..//* [@isDoc and (name()='LegalNewsHeadline' or name()='ArizonaAttorneyNewsCenterArticle')][(generate-id()=generate-id(key('years', umbraco.library:FormatDateTime(publicationDate,'yyyy'))))]">
    <xsl:sort select="publicationDate" order="descending"/>
    <xsl:sort select="@sortOrder" data-type="number" order="ascending" />

    <h3><strong><xsl:value-of select="Exslt.ExsltDatesAndTimes:year(publicationDate)"/></strong></h3>

    <xsl:for-each select="key('years',Exslt.ExsltDatesAndTimes:year(publicationDate)) [(generate-id()=generate-id(key('months', umbraco.library:FormatDateTime(publicationDate,'yyyyMMMM'))[1]))]">
    <xsl:sort select="publicationDate" order="descending"/>
    <xsl:sort select="@sortOrder" data-type="number" order="ascending" />

    <div style="margin-left:20px;">
    <h3><xsl:value-of select="Exslt.ExsltDatesAndTimes:monthname(publicationDate)"/></h3>

    <xsl:for-each select="key('months',umbraco.library:FormatDateTime(publicationDate,'yyyyMMMM'))">
    <xsl:sort select="publicationDate" order="descending"/>
    <xsl:sort select="@sortOrder" data-type="number" order="ascending" />

    <div style="margin-left:10px;">
    <div style="width:60px; float:left;"><xsl:value-of select="umbraco.library:FormatDateTime(publicationDate,'M/d/yy')"/></div>

    <div style="width:24px; float:left;">
    <xsl:if test="string(videoURL) != ''">
    <xsl:value-of select="Designit.VideoEmbed:VideoEmbedInLightBox(videoURL, headline, $videoHeight, $videoWidth, $previewHeight, $previewWidth, 1)" disable-output-escaping="yes"/>
    </xsl:if>
    </div>

    <div style="width:24px; float:left;">
    <xsl:if test="string(photo) != ''">
    <xsl:element name="a">
    <xsl:attribute name="href">
    <xsl:value-of select="umbraco.library:GetMedia(photo, 0)/umbracoFile"/>
    </xsl:attribute>
    <xsl:attribute name="title">
    <xsl:value-of select="headline"/>
    </xsl:attribute>
    <xsl:attribute name="class">photoThumb</xsl:attribute>
    <img src="/images/icons/picture.png" alt="View Photo" name="photo" width="16" height="16" hspace="0" vspace="0" border="0" id="photo" title="Click to view photo" />
    </xsl:element>
    </xsl:if>
    </div>

    <div style="margin-left:84px;">
    <p>
    <xsl:element name="a">
    <xsl:if test="name() = 'LegalNewsHeadline'">
    <xsl:if test="string(link/url-picker/new-window) = 'True'">
    <xsl:attribute name="target">_blank</xsl:attribute>
    </xsl:if>
    <xsl:attribute name="href">
    <xsl:choose>
    <xsl:when test="link/url-picker/@mode = 'URL'">
    <xsl:value-of select="link/url-picker/url"/>
    </xsl:when>
    <xsl:when test="link/url-picker/@mode= 'Content'">
    <xsl:value-of select="umbraco.library:NiceUrl(link/url-picker/node-id)"/>
    </xsl:when>
    <xsl:when test="link/url-picker/@mode = 'Media'">
    <xsl:value-of select="umbraco.library:GetMedia(link/url-picker/node-id,false())/umbracoFile"/>
    </xsl:when>
    <xsl:when test="link/url-picker/@mode = 'Upload'">
    <xsl:value-of select="link/url-picker/url"/>
    </xsl:when>
    <xsl:otherwise></xsl:otherwise>
    </xsl:choose>
    </xsl:attribute>
    </xsl:if>

    <xsl:if test="name() = 'ArizonaAttorneyNewsCenterArticle'">
    <xsl:attribute name="href">
    <xsl:value-of select="umbraco.library:NiceUrl(@id)"/>
    </xsl:attribute>
    </xsl:if>

    <xsl:value-of select="headline"/>
    </xsl:element></p>
    </div>
    </div>
    </xsl:for-each>
    </div>
    </xsl:for-each>
    <br />
    </xsl:for-each>

    <script type="text/javascript">
    $("a.photoThumb").fancybox({
    'padding': 1,
    'autoScale': true,
    'transitionIn': 'none',
    'transitionOut': 'none',

    'hideOnOverlayClick': true,
    'hideOnContentClick': true,
    'titlePosition': 'inside',
    'centerOnScroll': true,
    'title': this.title
    })
    $.fancybox.resize;
    </script>

    </xsl:template>

    </xsl:stylesheet>

  • Chriztian Steinmeier 2726 posts 8320 karma points MVP 4x admin c-trib
    Feb 08, 2012 @ 20:35
    Chriztian Steinmeier
    0

    Hi Connie,

    Large chunk of code - hard job to "just paginate", but I've got something you can try:

    I have created a "_PaginationHelper.xslt" file that should be suitable for this - currently it's on GitHub - you can get it here: _PaginationHelper.xslt

    What you need to do is:

    1. Include the helper with <xsl:include href="_PaginationHelper.xslt" /> (just add that in the bottom of the main XSLT file)

    2. Take the chunk of HTML you're generating in the innermost for-each, and extract that to a separate template

    3. Instead of the <xsl:for-each> you then collect the node ids that needs to be output, and put them in a "proxy" variable (we need to create a new sorted set because the nodes will otherwise render in document order).

    4. Call the PaginateSelection template and send it your proxy to render a page of data

    Something like this:

    <xsl:stylesheet>
    
        <xsl:template match="/">
    
            <xsl:for-each select="...">
    
                <xsl:for-each select="...">
    
                    <!-- This is where the innermost <xsl:for-each> was -->
                    <xsl:variable name="sortedDataProxy">
                        <xsl:for-each select="key('months', umbraco.library:FormatDateTime(publicationDate,'yyyyMMMM'))">
                            <xsl:sort select="publicationDate" order="descending" />
                            <xsl:sort select="@sortOrder" data-type="number" order="ascending" />
                            <!-- Just record the id -->
                            <nodeId><xsl:value-of select="@id" /></nodeId>
                        </xsl:for-each>
                    </xsl:variable>
                    <!-- Need to convert to nodeset for XPath navigation in proxy -->
                    <xsl:variable name="sortedData" select="msxml:node-set($sortedDataProxy)/nodeId" />
    
                    <!-- Do the magic thing -->
                    <xsl:call-template name="PaginateSelection">
                        <xsl:with-param name="selection" select="$sortedData" />
                    </xsl:call-template>
    
                </xsl:for-each>
    
            </xsl:for-each>
    
        </xsl:template>
    
        <!-- Template for each item in the paginated set -->
        <xsl:template match="LegalNewsHeadline | ArizonaAttorneyNewsCenterArticle">
    
            <!-- Chunk from innermost <xsl:for-each> here -->
    
        </xsl:template>
    
        <!-- Template to invoke the template above on the nodes from the sorted set -->
        <xsl:template match="nodeId">
            <xsl:apply-templates select="umbraco.library:GetXmlNodeById(.)" />
        </xsl:template>           
    
        <!-- Get help ... -->
        <xsl:include href="_PaginationHelper.xslt" />
    
    </xsl:stylesheet>

     

    Now this may seem like a lot of hoopla - but that's because of two things: 1: Your XSLT has everything inside a single template which isn't the optimal scenario for my helper; and 2: We need to pre-sort the nodes because we can't specify sorting inside the select statement.

    Hopefully you get to a point where something's working and we can take it from there :-)

    /Chriztian

     

  • Connie DeCinko 931 posts 1159 karma points
    Sep 29, 2012 @ 00:03
    Connie DeCinko
    0

    Close but not quite.  This is giving me Prev/Next for each date instead of for the entire result set.

    Also, the Prev/Next and page numbers render as a bulleted list.

  • Connie DeCinko 931 posts 1159 karma points
    Sep 29, 2012 @ 00:05
    Connie DeCinko
    0

    Here is a simpler version of my original script without all the bells and whistles.  This still has the grouping by year and then by month.

     

    <?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:Designit.VideoEmbed="urn:Designit.VideoEmbed" 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="html" omit-xml-declaration="yes"/>

      <xsl:param name="currentPage"/>

      <xsl:key name="years" match="* [@isDoc and (name()='LegalNewsHeadline' or name()='ArizonaAttorneyNewsCenterArticle')]" use="umbraco.library:FormatDateTime(publicationDate, 'yyyy')"/>
      <xsl:key name="months" match="* [@isDoc and (name()='LegalNewsHeadline' or name()='ArizonaAttorneyNewsCenterArticle')]" use="umbraco.library:FormatDateTime(publicationDate, 'yyyyMMMM')"/>

      <xsl:template match="/">

        <xsl:value-of select="umbraco.library:RegisterJavaScriptFile('fancybox', '/scripts/Designit.VideoEmbed/jquery.fancybox-1.3.1.pack.js')"/>
        <xsl:value-of select="umbraco.library:RegisterStyleSheetFile('cssFancyBox', '/css/Designit.VideoEmbed/jquery.fancybox-1.3.1.css')"/>

        <xsl:for-each select="$currentPage/..//* [@isDoc and (name()='LegalNewsHeadline' or name()='ArizonaAttorneyNewsCenterArticle')][(generate-id()=generate-id(key('years', umbraco.library:FormatDateTime(publicationDate,'yyyy'))))]">
          <xsl:sort select="publicationDate" order="descending"/>
          <xsl:sort select="@sortOrder" data-type="number" order="ascending" />

          <h3><strong><xsl:value-of select="Exslt.ExsltDatesAndTimes:year(publicationDate)"/></strong></h3>

          <xsl:for-each select="key('years',Exslt.ExsltDatesAndTimes:year(publicationDate)) [(generate-id()=generate-id(key('months', umbraco.library:FormatDateTime(publicationDate,'yyyyMMMM'))[1]))]">
            <xsl:sort select="publicationDate" order="descending"/>
            <xsl:sort select="@sortOrder" data-type="number" order="ascending" />
          
            <div style="margin-left:20px;">
              <h3><xsl:value-of select="Exslt.ExsltDatesAndTimes:monthname(publicationDate)"/></h3>

              <xsl:for-each select="key('months',umbraco.library:FormatDateTime(publicationDate,'yyyyMMMM'))">
               
                <!-- This is where the innermost <xsl:for-each> was -->
                <xsl:variable name="sortedDataProxy">
                  <xsl:for-each select="key('months', umbraco.library:FormatDateTime(publicationDate,'yyyyMMMM'))">
                    <xsl:sort select="publicationDate" order="descending" />
                    <xsl:sort select="@sortOrder" data-type="number" order="ascending" />
                    
                    <!-- Just record the id -->
                    <nodeId><xsl:value-of select="@id" /></nodeId>
                  </xsl:for-each>
                </xsl:variable>
                
                <!-- Need to convert to nodeset for XPath navigation in proxy -->
                <xsl:variable name="sortedData" select="msxml:node-set($sortedDataProxy)/nodeId" />
                
                <!-- Do the magic thing -->
                <xsl:call-template name="PaginateSelection">
                  <xsl:with-param name="selection" select="$sortedData" />
                </xsl:call-template>

              </xsl:for-each>
            </div>
          </xsl:for-each>
          <br />
        </xsl:for-each>
      </xsl:template>
            
      <!-- Template for each item in the paginated set -->
      <xsl:template match="LegalNewsHeadline | ArizonaAttorneyNewsCenterArticle">
        <p><xsl:value-of select="headline"/></p>
      </xsl:template>
       
      <!-- Template to invoke the template above on the nodes from the sorted set -->
      <xsl:template match="nodeId">
        <xsl:apply-templates select="umbraco.library:GetXmlNodeById(.)" />
      </xsl:template>
            
      <!-- Get help ... -->
      <xsl:include href="_PaginationHelper.xslt" />
    </xsl:stylesheet>
  • Chriztian Steinmeier 2726 posts 8320 karma points MVP 4x admin c-trib
    Oct 03, 2012 @ 07:56
    Chriztian Steinmeier
    0

    Here's a condensed chunk of how to do this (from this discussion on GitHub):

    <!-- Select all the nodes to paginate -->
    <xsl:variable name="nodes" select="/root/Page" />
    
    <xsl:variable name="sortedProxy">
        <xsl:for-each select="$nodes">
            <xsl:sort select="eventDate" data-type="text" order="descending" />
            <xsl:sort select="substring-after(@nodeName, 'Item ')" data-type="number" order="ascending" />
            <!-- Store the id and date -->
            <nodeId date="{eventDate}"><xsl:value-of select="@id" /></nodeId>
        </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="sorted" select="msxsl:node-set($sortedProxy)/nodeId" />
    
    <xsl:template match="/">
        <body>
            <xsl:call-template name="PaginateSelection">
                <xsl:with-param name="selection" select="$sorted" />
                <xsl:with-param name="perPage" select="3" />
            </xsl:call-template>
        </body>
    </xsl:template>
    
    <xsl:template match="nodeId">
        <!-- Because the set is pre-sorted we can use simple grouping (e.g., checking the previous item)  -->
        <xsl:variable name="precedingDate" select="preceding-sibling::nodeId[1]/@date" />
        <xsl:variable name="thisYear" select="substring(@date, 1, 4)" />
        <xsl:variable name="thisMonth" select="substring(@date, 1, 7)" />
    
        <!-- Print the year? -->
        <xsl:if test="position() = 1 or not($thisYear = substring($precedingDate, 1, 4))">
            <h2><xsl:value-of select="$thisYear" /></h2>
        </xsl:if>
    
        <!-- Print the month? -->
        <xsl:if test="position() = 1 or not($thisMonth = substring($precedingDate, 1, 7))">
            <h3><xsl:apply-templates select="@date" mode="date.month" /></h3>
        </xsl:if>
    
        <!-- Output the item -->
        <xsl:apply-templates select="$nodes[@id = current()]" />
    </xsl:template>
    
    <!-- Template for the actual items you want to output -->
    <xsl:template match="Page">
        <p>
            <xsl:apply-templates select="eventDate" mode="date.simple" />
            <xsl:text>: </xsl:text>
            <xsl:value-of select="@nodeName" />
        </p>
    </xsl:template>
    
    <!-- :: Date formatters :: -->
    <xsl:template match="* | @*" mode="date.simple">
        <xsl:value-of select="substring-before(., 'T')" />
    </xsl:template>
    
    <xsl:template match="* | @*" mode="date.month">
        <!-- E.g., you could get the monthname using an extension -->
        <xsl:value-of select="substring(., 6, 2)" />
    </xsl:template>
    
    <xsl:include href="_PaginationHelper.xslt" />

    The thing to notice: When using a pre-sorted, the advanced grouping stuff is no longer necessary...

    /Chriztian

  • 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