RE: [xsl] Omnimark vs. XSL (Saxon) Challenge

Subject: RE: [xsl] Omnimark vs. XSL (Saxon) Challenge
From: "Michael Kay" <mhk@xxxxxxxxx>
Date: Tue, 16 Mar 2004 23:43:18 -0000
Like others, I don't feel I have enough information about the problem to
offer you a solution, but I can attempt a critique of your code.

<xsl:variable name="rows">
	<xsl:value-of select="count($root//row)" />
</xsl:variable>

Two major inefficiencies here. Firstly, you want a number, not a result tree
fragment. Secondly, you know where the row elements are, so you don't need
//. Write:

<xsl:variable name="rows" select="count($root/tbody/row)"/>

Now:

<xsl:variable name="cols">
	<xsl:variable name="first-row">
		<xsl:for-each select="$root//row[1]/entry">
			<entry>
				<xsl:attribute name="colspan">
					<xsl:choose>
						<xsl:when test="@colspan
&gt; 1"><xsl:value-of select="@colspan"/></xsl:when>
						<xsl:otherwise><xsl:value-of
select="1"/></xsl:otherwise>
					</xsl:choose>
				</xsl:attribute>
			</entry>
		</xsl:for-each>
	</xsl:variable>
	<xsl:value-of select="sum($first-row/entry/@colspan)" />
</xsl:variable>

You may not realize it, but this isn't correct under XSLT 1.0, because
you're not allowed to use an RTF variable in a path expression. So you might
as well go the whole hog and do it the XSLT 2.0 way:

<xsl:variable name="cols" 
     select="sum(for $e in $root/tbody/row[1]/entry return max(($i/@colspan,
1)))"/>

If you prefer XSLT 1.0, try:

<xsl:variable name="cols" select=
"sum($root/tbody/row[1]/@colspan[. &gt; 1]) + 
  count($root/tbody/row[1]/entry[not(@colspan &gt; 1)])"/>

Now:

<xsl:variable name="empty-cells">
	<xsl:variable name="random-nodes-r" select="document('')//*" />
	<xsl:variable name="random-nodes-c" select="document('')//*" />
	<xsl:for-each select="$random-nodes-r[position() &lt;= $rows]">
		<xsl:variable name="row-num" select="position()" />
		<xsl:for-each select="$random-nodes-c[position() &lt;=
$cols]">
			<xsl:variable name="col-num" select="position()" />
			<cell row="{$row-num}" col="{$col-num}" />
		</xsl:for-each>
	</xsl:for-each>
</xsl:variable><!-- empty-cells -->

This is using the "1 to n" iteration trick. Using the stylesheet as a place
to get the nodes for this seems a bad choice, document('') involves an extra
parse, though it will only be done once. I would do this one by recursion.
(Again, it's much easier in 2.0). But then I would want to take a careful
look at your algorithm to see if it really has to be done this way.

None of the above, of course, is critical to the total performance of your
stylesheet, which depends on the recursive phase that follows. I'm sorry,
but I've been staring at it for more time than I can afford, and I don't
understand the algorithm that it's implementing.

How long does it take, and how does the elapsed time vary as the table size
increases? Plotting that can often deepen your understanding of what you are
asking the XSLT processor to do.

Michael Kay








 

# -----Original Message-----
# From: owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx 
# [mailto:owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx] On Behalf Of 
# Michael Müller-Hillebrand
# Sent: 16 March 2004 14:07
# To: XSL-List
# Subject: [xsl] Omnimark vs. XSL (Saxon) Challenge
# 
# Dear experts,
# 
# Recently I was quite unimpressed by the presentation of an 
# Omnimark script requiring 32 seconds to make what seemed like 
# a little change to a 2000 cells table. I said, this would be 
# possible with XSL as well, and suddenly I found myself challenged.
# 
# After some hours I have a working solution but it is so 
# slow... I hope I have missed something important with my 
# method and now I am seeking assistance.
# 
# The task seemed simple at first:
# 
# HTML tables usually have width attributes for each cell. CALS 
# and some other table models require all column widths to be 
# specified at the top level, e.g. as an attribute of the table 
# element. 
# 
# Input table:
# 
# <table>
#   <tbody>
#     <row>
#       <entry colspan="2" rowspan="2" width="70%">I</entry>
#       <entry colspan="2" width="30%">II</entry>
#     </row>
#     ...
#   </tbody>
# </table>
# 
# Desired output:
# 
# <table width="48mm 36mm 24mm 12mm">
#   <tbody>
#     <row>
#       <entry colspan="2" rowspan="2">I</entry>
#       <entry colspan="2">II</entry>
#     </row>
#     ...
#   </tbody>
# </table>
# 
# The main problem is the use of colspan and rowspan, which 
# makes it hard for any cell to know to which column it 
# belongs. One has to render the table from start to finish to 
# learn that for each cell.
# 
# I read about Michael Kay's "Knight's Tour Stylesheet" and 
# created a very recursive similar thing. I recursively loop 
# through all rows, through all cells, within spanned cells 
# through all rowspans and then through all colspans.
# 
# I would very much appreciate any comments and will gladly summarize.
# 
# Please find links to the stylesheet and sample files at 
# 
# http://cap-studio.de/test/challenge.html
# 
# Thanks a lot,
# 
# - Michael
# --
# ________________________________________________________
# Michael Müller-Hillebrand, cap studio, Erlangen, Germany 
# http://cap-studio.de/en/ Increase Knowledge Worker's 
# Efficiency using FrameMaker, XML/XSL, FrameScript, WebWorks 
# Publisher,...
# 
#  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
# 
# 


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread