Subject: Re: [xsl] XSLT repetition constructs comparison From: "Martin Honnen martin.honnen@xxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Thu, 14 Jan 2021 10:28:38 -0000 |
as="xs:integer"/>Hi all, B B I'm comparing the functionality of, XSLTB 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> B B <student> B B B <rollNo>1</rollNo> B B B <fName>Sharon</fName> B B B <lName>Adler</lName> B B </student> B B <student> B B B <rollNo>2</rollNo> B B B <fName>Anders</fName> B B B <lName>Berglund</lName> B B </student> B B <student> B B B <rollNo>3</rollNo> B B B <fName>Norm</fName> B B B <lName>Walsh</lName> B B </student> B B <student> B B B <rollNo>4</rollNo> B B B <fName>Michael</fName> B B B <lName>Sperberg-McQueen</lName> B B </student> B B <student> B B B <rollNo>5</rollNo> B B B <fName>Florent</fName> B B B <lName>Georges</lName> B B </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>">
B B <xsl:output method="html" indent="yes"/>
B B <xsl:template match="students"> B B B <html> B B B B <head> B B B B B B <title>Student list</title> B B B B </head> B B B B <body> B B B B B B <table> B B B B B B B <tr> B B B B B B B B B <td><b>Roll No.</b></td> B B B B B B B B B <td><b>First name</b></td> B B B B B B B B B <td><b>Last name</b></td> B B B B B B B </tr> B B B B B B B <xsl:for-each select="student"> B B B B B B B B B <xsl:sort select="fName"/> B B B B B B B B B <xsl:sort select="lName"/> B B B B B B B B B <tr> B B B B B B B B B B <td align="center"><xsl:value-of select="rollNo"/>.</td> B B B B B B B B B B <td><xsl:value-of select="fName"/></td> B B B B B B B B B B <td><xsl:value-of select="lName"/></td> B B B B B B B B B </tr> B B B B B B B </xsl:for-each> B B B B B B B <tr> B B B B <td colspan="3"> </td> B B B </tr> B B B <tr> B B B B <td colspan="2"><b>Total no of students</b> : </td> B B B B <td><xsl:value-of select="count(student)"/></td> B B B B B B B </tr> B B B B B B </table> B B B B </body> B B B </html> B B </xsl:template>
</xsl:stylesheet>
(2)B 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>"
B xmlns:xs="http://www.w3.org/2001/XMLSchema <http://www.w3.org/2001/XMLSchema>"
B exclude-result-prefixes="xs">
B B <xsl:output method="html" indent="yes"/>
B B <xsl:template match="students"> B B B <html> B B B B <head> B B B B B B <title>Student list</title> B B B B </head> B B B B <body> B B B B B B <table> B B B B B B B <tr> B B B B B B B B B <td><b>Roll No.</b></td> B B B B B B B B B <td><b>First name</b></td> B B B B B B B B B <td><b>Last name</b></td> B B B B B B B </tr> B B B B B B B <xsl:iterate select="student"> B B B B B B B B B <xsl:param name="total" select="0"
students</b> : </td>B B B B B B B B B <xsl:on-completion> B B B B B B B B B B <tr> B B B B B B B B B B B B <td colspan="3"> </td> B B B B B B B B B B </tr> B B B B B B B B B B <tr> B B B B B B B B B B B <td colspan="2"><b>Total no of
1"/>B B B B B B B B B B B <td><xsl:value-of select="$total"/></td> B B B B B B B B B B </tr> B B B B B B B B B </xsl:on-completion> B B B B B B B B B <tr> B B B B B B B B B B <td align="center"><xsl:value-of select="rollNo"/>.</td> B B B B B B B B B B <td><xsl:value-of select="fName"/></td> B B B B B B B B B B <td><xsl:value-of select="lName"/></td> B B B B B B B B B </tr> B B B B B B B B B <xsl:next-iteration> B B B B B B B B B B <xsl:with-param name="total" select="$total +
as="xs:integer"/>B B B B B B B B B </xsl:next-iteration> B B B B B B B </xsl:iterate> B B B B B B </table> B B B B </body> B B B </html> B B </xsl:template>
</xsl:stylesheet>
(3)B 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>"
B xmlns:xs="http://www.w3.org/2001/XMLSchema <http://www.w3.org/2001/XMLSchema>"
B exclude-result-prefixes="xs">
B B <xsl:output method="html" indent="yes"/>
B B <xsl:template match="students"> B B B <html> B B B B <head> B B B B B B <title>Student list</title> B B B B </head> B B B B <body> B B B B B B <table> B B B B B B B <tr> B B B B B B B B B <td><b>Roll No.</b></td> B B B B B B B B B <td><b>First name</b></td> B B B B B B B B B <td><b>Last name</b></td> B B B B B B B </tr> B B B B B B B <xsl:variable name="result_1" as="element(tr)*"> B B B B B B B B B <xsl:iterate select="student"> B B B B B B B B B B <xsl:param name="total" select="0"
students</b> :B B B B B B B B B B <xsl:on-completion> B B B B B B B B B B B B <tr> B B B B B B B B B B B B B <td colspan="3"> </td> B B B B B B B B B B B B </tr> B B B B B B B B B B B B <tr> B B B B B B B B B B B B B <td colspan="2"><b>Total no of
select="$total"/></td></td> B B B B B B B B B B B B B <td><xsl:value-of
select="$total + 1"/>B B B B B B B B B B B B </tr> B B B B B B B B B B </xsl:on-completion> B B B B B B B B B B <tr> B B B B B B B B B B B B <td align="center"><xsl:value-of select="rollNo"/>.</td> B B B B B B B B B B B B <td><xsl:value-of select="fName"/></td> B B B B B B B B B B B B <td><xsl:value-of select="lName"/></td> B B B B B B B B B B </tr> B B B B B B B B B B <xsl:next-iteration> B B B B B B B B B B B B <xsl:with-param name="total"
B B B B B B B B B B </xsl:next-iteration> B B B B B B B B B </xsl:iterate> B B B B B B B </xsl:variable> B B B B B B B <xsl:perform-sort select="$result_1[position() le (count($result_1)-2)]"> B B B B B B B B B <xsl:sort select="td[2]"/> B B B B B B B B B <xsl:sort select="td[3]"/> B B B B B B B </xsl:perform-sort> B B B B B B B <xsl:copy-of select="$result_1[position() gt (count($result_1)-2)]"/> B B B B B B </table> B B B B </body> B B B </html> B B </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?
I agree with Michael that you can always use fn:sort for the select expression of xsl:iterate in XSLT 3 or at least, in Saxon 9.8 and 9.9 HE where the higher-order variant of fn:sort is not available, roll your own sort function with xsl:function and xsl:perform sort that you then call in the select attribute of xsl:iterate.
In general, for that use case, I don't see why xsl:iterate is better than xsl:for-each. I would probably use push style processing with xsl:apply-templates.
Last, for the use with the variable, don't forget that `xsl:perform-sort` can be directly applied to result constructed by nested XSLT so you could also use
<xsl:perform-sort> <xsl:sort select="td[2]"/> <xsl:sort select="td[3]"/> <xsl:iterate select="student"> ... </xsl:iterate> </xsl:perform-sort>
perhaps although I guess that will not work with the total column you want to treat differently.
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] XSLT repetition construct, Mukul Gandhi mukulg@ | Thread | Re: [xsl] XSLT repetition construct, Mukul Gandhi mukulg@ |
Re: [xsl] XSLT repetition construct, Michael Kay mike@xxx | Date | Re: [xsl] XSLT repetition construct, Mukul Gandhi mukulg@ |
Month |