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
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--