0

I know there are some questions about this here, and I tried a lot of solutions around but i'm still stuck. I tried to use this pagination in xsl and this Possible to split XML into multiple pages with XSLT? but don't get what I need,

I need to create a pagination in my generated html, using a XML through a XSLT parser.

XML file is like this

<root>
    <result>
        <a>field one</a>
        <b>field two</b>
        <c>field three</c>
    </result>
    <result>
        <a>hello</a>
        <b>thanks</b>
        <c>for help</c>
    </result>
    <result>
        <a>thank</a>
        <b>you</b>
        <c>!!</c>
    </result>
    ..... 
</root>

and my XSLT without pagination is this

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    xmlns:user="http://mycompany.com/mynamespace">


    <xsl:output method="html" indent="yes" />

    <xsl:template match="/">
        <html>
            <body>
                <xsl:apply-templates />
            </body>
        </html>
    </xsl:template>

    <xsl:template match="root">
                    <xsl:for-each select="result">
                        <div class="list_item">
                            <div class="dmv_line">
                                <div class="box_text">
                                    <h2><xsl:value-of select="a"/></h2>
                                </div>
                                </div>
                                <div class="dmv_line">
                                    <div class="box_text">
                                        <h2><xsl:value-of select="b"/></h2>
                                    </div>
                                </div>
                                <div class="dmv_line">
                                    <div class="box_text">
                                        <h2><xsl:value-of select="c"/></h2>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </xsl:for-each>
    </xsl:template>


</xsl:stylesheet>

What I need is to create a <div> that encapsulate results 3 by 3 or 4 by 4, which I will make hide or visible in javascript later.. Thanks

[EDIT]: The HTML output, if I assume to make pagination 2 elements per page, and considering only the 3 elements in example, the output should be

<-- page number one --->
<div id="1">
 <div class="list_item">
     <div class="dmv_line">
        <div class="box_text">
            <h2>field one</h2>
        </div>
     </div>
    <div class="dmv_line">
        <div class="box_text">
            <h2>field two</h2>
        </div>
     </div>
     <div class="dmv_line">
        <div class="box_text">
            <h2>field three</h2>
        </div>
     </div>
    </div>
     <div class="list_item">
         <div class="dmv_line">
            <div class="box_text">
                <h2>hello</h2>
            </div>
         </div>
        <div class="dmv_line">
            <div class="box_text">
                <h2>thanks</h2>
            </div>
         </div>
         <div class="dmv_line">
            <div class="box_text">
                <h2>for help</h2>
            </div>
         </div>
    </div>
</div>
 <-- END OF page number one --->
 <-- page number two --->
<div id="2">     
     <div class="list_item">
         <div class="dmv_line">
            <div class="box_text">
                <h2>thank</h2>
            </div>
         </div>
        <div class="dmv_line">
            <div class="box_text">
                <h2>you</h2>
            </div>
         </div>
         <div class="dmv_line">
            <div class="box_text">
                <h2>!!!</h2>
            </div>
         </div>
    </div>
</div>  
 <-- END OF page number two --->
1
  • 1
    It would help if you gave a sample of the html you are expecting to output when you have pagination. Thanks! Commented Oct 16, 2013 at 22:24

1 Answer 1

1

For problems like this, the approach is to firstly select the elements that will occur first on each of your 'pages'. This is achieved by checking its position.

<xsl:for-each select="result[position() mod $size = 1]">

So, if the $size variable is set to 2, this would select the result elements in positions 1, 3, 5, etc...

Within this loop, you can then output the containing div tag for the 'age'

<div id="{position()}">  

Note that position is context-sensitive, and will return the position of the node in the node set you have just selected (i.e. it will return 1, 2, 3, etc)

Finally, to get the result elements that make up the 'page' you can select them like so

<xsl:apply-templates select="self::*|following-sibling::*[position() &lt; $size]" />

And the template that matches them would effectively be like your existing code in the xsl:for-each.

Try the following XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:param name="size" select="2"/>

   <xsl:output method="html" indent="yes"/>

   <xsl:template match="/">
      <html>
         <body>
            <xsl:apply-templates/>
         </body>
      </html>
   </xsl:template>

   <xsl:template match="root">
      <xsl:for-each select="result[position() mod $size = 1]">
         <div id="{position()}">
            <xsl:apply-templates select="self::*|following-sibling::*[position() &lt; $size]"/>
         </div>
      </xsl:for-each>
   </xsl:template>

   <xsl:template match="result">
      <div class="list_item">
         <div class="dmv_line">
            <div class="box_text">
               <h2>
                  <xsl:value-of select="a"/>
               </h2>
            </div>
         </div>
         <div class="dmv_line">
            <div class="box_text">
               <h2>
                  <xsl:value-of select="b"/>
               </h2>
            </div>
         </div>
         <div class="dmv_line">
            <div class="box_text">
               <h2>
                  <xsl:value-of select="c"/>
               </h2>
            </div>
         </div>
      </div>
   </xsl:template>
</xsl:stylesheet>

This should hopefully give you the output you need.

As an aside, you have a bit of code repetition in your code. Try replacing the template that matches result with these two templates instead:

<xsl:template match="result">
   <div class="list_item"> 
      <xsl:apply-templates select="a|b|c" />
   </div>
</xsl:template>

<xsl:template match="result/*">
      <div class="dmv_line">
         <div class="box_text">
            <h2>
               <xsl:value-of select="."/>
            </h2>
         </div>
       </div>
</xsl:template>
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot! work perfect. And also thanks for your aside solution, but my html have more class beside the "box_text", I just give a shorter example :) +1 before I tried, and accept answer when checked is ok! Thanks again

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.