[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] XSLT repetition constructs comparison
Hi all, I'm comparing the functionality of, XSLT repetition constructs xsl:for-each and xsl:iterate (versions 2.0 & 3.0). Below is my example use case, and the corresponding XSLT solutions from my side, XML input document: <?xml version="1.0"?> <students> <student> <rollNo>1</rollNo> <fName>Sharon</fName> <lName>Adler</lName> </student> <student> <rollNo>2</rollNo> <fName>Anders</fName> <lName>Berglund</lName> </student> <student> <rollNo>3</rollNo> <fName>Norm</fName> <lName>Walsh</lName> </student> <student> <rollNo>4</rollNo> <fName>Michael</fName> <lName>Sperberg-McQueen</lName> </student> <student> <rollNo>5</rollNo> <fName>Florent</fName> <lName>Georges</lName> </student> </students> I wish to transform, the above XML data into HTML, using XSLT. The resulting HTML, needs to have a table containing rows representing each XML input "student" element, and a total record count at the bottom of HTML output. Below are my various XSLT solutions, (1) An XSLT 2.0 solution, with sorting (sorting by fName & lName): <?xml version="1.0"?> <xsl:stylesheet version="2.0" xmlns:xsl=" http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes"/> <xsl:template match="students"> <html> <head> <title>Student list</title> </head> <body> <table> <tr> <td><b>Roll No.</b></td> <td><b>First name</b></td> <td><b>Last name</b></td> </tr> <xsl:for-each select="student"> <xsl:sort select="fName"/> <xsl:sort select="lName"/> <tr> <td align="center"><xsl:value-of select="rollNo"/>.</td> <td><xsl:value-of select="fName"/></td> <td><xsl:value-of select="lName"/></td> </tr> </xsl:for-each> <tr> <td colspan="3"> </td> </tr> <tr> <td colspan="2"><b>Total no of students</b> : </td> <td><xsl:value-of select="count(student)"/></td> </tr> </table> </body> </html> </xsl:template> </xsl:stylesheet> (2) An XSLT 3.0 solution, without sorting: <?xml version="1.0"?> <xsl:stylesheet version="3.0" xmlns:xsl=" http://www.w3.org/1999/XSL/Transform" xmlns:xs=" http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"> <xsl:output method="html" indent="yes"/> <xsl:template match="students"> <html> <head> <title>Student list</title> </head> <body> <table> <tr> <td><b>Roll No.</b></td> <td><b>First name</b></td> <td><b>Last name</b></td> </tr> <xsl:iterate select="student"> <xsl:param name="total" select="0" as="xs:integer"/> <xsl:on-completion> <tr> <td colspan="3"> </td> </tr> <tr> <td colspan="2"><b>Total no of students</b> : </td> <td><xsl:value-of select="$total"/></td> </tr> </xsl:on-completion> <tr> <td align="center"><xsl:value-of select="rollNo"/>.</td> <td><xsl:value-of select="fName"/></td> <td><xsl:value-of select="lName"/></td> </tr> <xsl:next-iteration> <xsl:with-param name="total" select="$total + 1"/> </xsl:next-iteration> </xsl:iterate> </table> </body> </html> </xsl:template> </xsl:stylesheet> (3) An XSLT 3.0 solution, with sorting: <?xml version="1.0"?> <xsl:stylesheet version="3.0" xmlns:xsl=" http://www.w3.org/1999/XSL/Transform" xmlns:xs=" http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"> <xsl:output method="html" indent="yes"/> <xsl:template match="students"> <html> <head> <title>Student list</title> </head> <body> <table> <tr> <td><b>Roll No.</b></td> <td><b>First name</b></td> <td><b>Last name</b></td> </tr> <xsl:variable name="result_1" as="element(tr)*"> <xsl:iterate select="student"> <xsl:param name="total" select="0" as="xs:integer"/> <xsl:on-completion> <tr> <td colspan="3"> </td> </tr> <tr> <td colspan="2"><b>Total no of students</b> : </td> <td><xsl:value-of select="$total"/></td> </tr> </xsl:on-completion> <tr> <td align="center"><xsl:value-of select="rollNo"/>.</td> <td><xsl:value-of select="fName"/></td> <td><xsl:value-of select="lName"/></td> </tr> <xsl:next-iteration> <xsl:with-param name="total" select="$total + 1"/> </xsl:next-iteration> </xsl:iterate> </xsl:variable> <xsl:perform-sort select="$result_1[position() le (count($result_1)-2)]"> <xsl:sort select="td[2]"/> <xsl:sort select="td[3]"/> </xsl:perform-sort> <xsl:copy-of select="$result_1[position() gt (count($result_1)-2)]"/> </table> </body> </html> </xsl:template> </xsl:stylesheet> I haven't mentioned the solution, where we could use xsl:apply-templates instead of xsl:for-each or xsl:iterate. Firstly, I find xsl:iterate much more functionally rich (except that it doesn't provide native sorting support) than xsl:for-each, if there's a requirement of XSLT sequential looping. If there's no requirement for sorting, then in XSLT 3.0 environment, I'd opt to use xsl:iterate. If there's requirement for sorting, then in XSLT 3.0 environment, I might opt to use xsl:for-each instead of xsl:iterate (does anybody differ?). When using XSLT 3.0 xsl:iterate, with a requirement of sorting, can anyone suggest a different (and possibly better as well) solution than (3) above? Any thoughts, about performance aspects of various XSLT solutions relevant to this thread, would also be useful to know. -- Regards, Mukul Gandhi
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|