Re: [xsl] XSLT repetition constructs comparison

Subject: Re: [xsl] XSLT repetition constructs comparison
From: "Michael Kay mike@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 14 Jan 2021 09:19:30 -0000
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">&#xa0;</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">&#xa0;</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">&#xa0;</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 <>)

Current Thread