Thursday, December 1, 2011

Paging in Xslt

This post shows how to do paging in xslt.
I needed it to display records from an xml file which came from a webpart code behind(code only webpart).
This post shows how to apply paging in an xslt  for a "for-each" loop.
I have mentioned the comments in green for better understanding.

1. First we declare some global variables in xslt.


<!-- Items to display on a page -->
  <xsl:variable name="pageSize" select="3"/>
  <!-- Count the total no of records -->
  <xsl:variable name="recordCount" select="count(/root/items/item)"/>

2.Now we declare a global parameter.

 <!--current page paramete which is passed on from code behind thhrough query string-->
  <xsl:param name="page">
    <!--setting the page parameter -->
    <xsl:choose>
      <xsl:when test="$page &gt; 1">
        <xsl:value-of select="$page"></xsl:value-of>
      </xsl:when>
      <xsl:otherwise>
        1
      </xsl:otherwise>
    </xsl:choose>
  </xsl:param>

3.Now starts our main template for the page.

<!-- the template for the xml doc starts here "root" is the root element in the xml doc-->
  <xsl:template match="root">
 <!-- for-each loop begins and we display based on the position of the item-->
    <!--position function returns the posion of the item in the for loop ie
    the first item in items/item will have position 1,the 2nd item will have position 2 and so on.
    The celing function determines the page on which the item will be displayed.
    Both of these are built in xslt functions-->
    <xsl:for-each select="items/item">
      <!-- now we calculate the page number of the item  using ceiling function and compare it with the current      page if the item lies on the current page
    it is further processed to give its relevant xslt style otherwise we move on to the next item-->
           <xsl:if test="ceiling(position() div $pageSize) = $page">
        <div>Content of the item in items or Each record in the for loop or Each item of the items element in          the xml</div>
         </xsl:if>
    </xsl:for-each><!--for each for items end here-->

     <div>
 <!-- Here we call the template that we created for paging and pass on the parameters as follows
    the current page no,page size ie records to display on one page and total number of records-->
      <xsl:call-template name="Paging">
        <xsl:with-param name="currentPage" select="$page" />
        <xsl:with-param name="rowsPerPage" select="$pageSize" />
        <xsl:with-param name="totalRows" select="$recordCount" />
      </xsl:call-template>
    </div>
    </xsl:template><!--main template ends-->

<!--Now here starts the logic for creating paging template 
  this template creates first and last page llinks ,five page buttons at max at a time as links and previous and next links-->
  <xsl:template name="Paging">
    <xsl:param name="currentPage" />
    <xsl:param name="totalRows" />
    <xsl:param name="rowsPerPage" />
    <!--Here we calculate the total no of pages need to display the items-->
    <xsl:variable name="totPages" select="ceiling($totalRows div $rowsPerPage)" />
    <!--this condition checks the currentpage and displays the "first page" link if current page is not the 1st page-->
    <xsl:if test="$currentPage &gt; 1">
      <a href="?page=1">
        First
      </a>
      <a href="?page={$currentPage - 1}">
        <img src="/style library/petroceltic/images/backward.png" alt="prev" class="imageButton"></img>
      </a>
    </xsl:if>
    <!--Now we set the start page ie the 1st page number link on the page-->
    <xsl:variable name="pagStartPage">
      <xsl:choose>
        <xsl:when test="$currentPage &lt;= 5">1</xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$currentPage - 4"></xsl:value-of>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <!--Now we call the template for generating page number links on the page-->
    <!--we pass start page ,number of page links to diaplay,the current page and the total no of pages as parameters to the template-->
    <xsl:call-template name="PageNumbers">
      <xsl:with-param name="i" select="$pagStartPage"/>
      <xsl:with-param name="MaxPagelink" select="($pagStartPage+4)"/>
      <xsl:with-param name="currentPage" select="$currentPage"/>
      <xsl:with-param name="totPages" select="$totPages"/>
    </xsl:call-template>
    <!--this condition diplays the next page link 
here we check the current page is less than the total pages and display the next icon-->
    <xsl:if test="$currentPage &lt; $totPages" >
      <a href="?page={$currentPage + 1}" >
        <img src="/style library/petroceltic/images/forward.png" alt="next" class="imageButton"></img>
      </a>
    </xsl:if>
    <!-- Here we check if total records are not equal to zero followed by checking that the current page is not equal to the last page and display the last page link-->
    <xsl:if test="$totalRows!= 0">
      <xsl:if test="$currentPage != $totPages">
        <a href="?page={$totPages}">
          Last
        </a>
      </xsl:if>
    </xsl:if>
  </xsl:template>

  <!--this template generates the page number links -->
  <xsl:template name="PageNumbers">
    <xsl:param name="i" />
    <xsl:param name="MaxPagelink"/>
    <xsl:param name="currentPage" />
    <xsl:param name="totPages"/>

    <xsl:choose>
      <!--Here we check if the total pages is greater than max page link on the page else skip to otherwise tag-->
      <xsl:when test="$totPages &gt; $MaxPagelink">
        <!--Here we check check if current page is less than or equal to max page link to display on the page-->
        <xsl:if test="$i &lt;= $MaxPagelink">
          <xsl:choose>
            <!--this condition diaplays an enabled number link if it is not the current page-->
            <xsl:when test="$currentPage != $i">
              <a href="?page={$i}">
                <xsl:value-of select="$i"></xsl:value-of>
              </a>
            </xsl:when>
            <!--if its the current page it diables the link-->
            <xsl:otherwise>
             <span>
                  <xsl:value-of select="$i"></xsl:value-of>
                <span>
            </xsl:otherwise>
          </xsl:choose>
          <!--Here we call the template in a loop  untill it "i" equals the maxpagenumber link to display-->
          <xsl:call-template name="PageNumbers">
            <xsl:with-param name="i" select="($i + 1)"></xsl:with-param>
            <xsl:with-param name="MaxPagelink" select="$MaxPagelink"></xsl:with-param>
            <xsl:with-param name="currentPage" select="$currentPage" ></xsl:with-param>
            <xsl:with-param name="totPages" select="$totPages"> </xsl:with-param>
          </xsl:call-template>
        </xsl:if>
      </xsl:when>
      <!-- This tag is called if the no of pages or total pages is less than the maxpage number link -->
      <xsl:otherwise>
        <!--Here we check if the no of pages are more than one,if yes than only display the  page links-->
        <xsl:if test="$totPages &gt; 1">
          <xsl:if test="$i &lt;= $totPages">
          <!--this condition diaplays an enabled number link if it is not the current page-->
            <xsl:choose>
              <xsl:when test="$currentPage != $i">
                <a href="?page={$i}">
                  <xsl:value-of select="$i"></xsl:value-of>
                </a>
              </xsl:when>
              <!--if its the current page it diables the link-->
              <xsl:otherwise>
                <span>
                  <xsl:value-of select="$i"></xsl:value-of>
                <span>
              </xsl:otherwise>
            </xsl:choose>
             <!--Here we call the template in a loop  untill it "i" equals the maxpagenumber link to display-->
            <xsl:call-template name="PageNumbers">
              <xsl:with-param name="i" select="($i + 1)"></xsl:with-param>
              <xsl:with-param name="MaxPagelink" select="$MaxPagelink"></xsl:with-param>
              <xsl:with-param name="currentPage" select="$currentPage" ></xsl:with-param>
              <xsl:with-param name="totPages" select="$totPages"> </xsl:with-param>
            </xsl:call-template>
          </xsl:if>
        </xsl:if>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
   
4.Now to pass the parameter "page"  from the code behind.
You can use the page load method.
I was using  this paging in a sharepoint  code only webpart so I've used the "CreateChild Controls"
method to initialize the "page" parameter ,below is the code for it.

int Current Page;
 if (this.Page.Request.QueryString["page"] != null) 
//fetching the current page from the query tring
 CurrentPage = int.Parse(this.Page.Request.QueryString["page"]);/
 XsltArgumentList xal = new XsltArgumentList();
//passing the current page to page parameter of xslt
 xal.AddParam("page", String.Empty, CurrentPage);

The output will be :



Thanks and Regards
Soham Patel

For any queries  drop a mail at 
sohampatel105@gmail.com
If possible will revert back. 

4 comments:

  1. getting error: searchPara cannot be found. please help

    ReplyDelete
    Replies
    1. Remove this

      &k={$searchPara}

      from the entire code that you would have copied from here.
      As this was my requirement to read a second parameter.

      You can omit this.

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. I received a circular reference error in the initialization of the page variable. xsl:when test="$page > 1"

    ReplyDelete