[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: XSLT repetition constructs comparison
I would personally only use xsl:iterate where you need something that xsl:for-each can't do, such as early exit, or accumulation of parameter values. But an xsl:iterate with no parameters, no xsl:break, no xsl:on-completion is equivalent to xsl:for-each so there's no intrinsic reason to prefer one over the other. There may be implementation differences but that's processor-specific. If you need some of the features of xsl:iterate and also want sorting, then I would normally use the sort() function: <xsl:iterate select="sort(student, (), function($s){$s/(fName, lName))">... or if that's not possible (e.g because you need a descending sort), then sort first (into a variable) using xsl:perform-sort. Michael Kay Saxonica > On 14 Jan 2021, at 09:05, Mukul Gandhi mukulg@xxxxxxxxxxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > > 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 <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 <http://www.w3.org/1999/XSL/Transform>" > xmlns:xs="http://www.w3.org/2001/XMLSchema <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 <http://www.w3.org/1999/XSL/Transform>" > xmlns:xs="http://www.w3.org/2001/XMLSchema <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 > XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list> > EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/293509> (by email <>)
|
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
|