Subject: Unusual? table layout task From: Mike Kellstrand <kellstrand@xxxxxxxxx> Date: Thu, 17 Jun 2004 10:43:51 -0700 (PDT) |
I was asked to create a set of named templates that could take a set of elements and render them in a table progressing vertically down each column, with numbering. For instance: <items> <item>one</item> <item>two</item> <item>three</item> <item>four</item> </items> would transform to: 1. one 3. three 2. two 4. four One of the requirement is that the node "item" would not be fixed, they wanted to be able to pass in a node name. I believe this precludes some of the standard solutions because you can't create and call template names dynamically. What I did was to write a set of recursive named templates, to which you can pass the element name, the number of columns desired, etc. The 1st template recurses down the number of rows that will be needed. It then calls a 2nd template that recurses across each row rendering each element. Does that sound like a reasonable solution, or is there a much better way to do it? I will include my working solution (for FOP) at the end of the email. Thanks, Mike <!-- Layout a group of elements in a table, --> <!-- ordered vertically down each column --> <!-- --> <!-- itemNode: the element name to render in a table --> <!-- columns: the number of columns to create --> <!-- columnWidth: the width of each column --> <!-- indent: start-indent value for the table --> <!-- numberFormat: the xsl:number format used to number the items --> <xsl:template name="tableLayoutVertFlow"> <xsl:param name="itemNode"/> <xsl:param name="columns"/> <xsl:param name="columnWidth"/> <xsl:param name="indent"/> <xsl:param name="numberFormat"/> <!-- How many items will go into the table? --> <xsl:variable name="itemCount"> <xsl:value-of select="count(*[name()=$itemNode])"/> </xsl:variable> <!-- How many rows will the table have? --> <xsl:variable name="rows"> <xsl:value-of select="ceiling($itemCount div $columns)"/> </xsl:variable> <fo:table table-layout="fixed" start-indent="{$indent}"> <xsl:if test="$indent = ''"> <xsl:attribute name="start-indent">0cm</xsl:attribute> </xsl:if> <!-- Create the number of columns we need in the table --> <xsl:call-template name="makeTableColumns"> <xsl:with-param name="count"> <xsl:value-of select="$columns"/> </xsl:with-param> <xsl:with-param name="width"> <xsl:value-of select="$columnWidth"/> </xsl:with-param> </xsl:call-template> <fo:table-body> <!-- Call a recursive routine that lays out each table row --> <xsl:call-template name="startTableRow"> <xsl:with-param name="itemNode"> <xsl:value-of select="$itemNode"/> </xsl:with-param> <xsl:with-param name="rows"> <xsl:value-of select="$rows"/> </xsl:with-param> <xsl:with-param name="columns"> <xsl:value-of select="$columns"/> </xsl:with-param> <xsl:with-param name="itemCount"> <xsl:value-of select="$itemCount"/> </xsl:with-param> <xsl:with-param name="curRow"> <xsl:value-of select="1"/> </xsl:with-param> <xsl:with-param name="numberFormat"> <xsl:value-of select="$numberFormat"/> </xsl:with-param> </xsl:call-template> </fo:table-body> </fo:table> </xsl:template> <!-- This is a recursive routine that is called for each table row --> <!-- It is called initially with a curRow value of 1, and then recurses --> <!-- until the last row has been rendered --> <xsl:template name="startTableRow"> <xsl:param name="itemNode"/> <xsl:param name="rows"/> <xsl:param name="columns"/> <xsl:param name="itemCount"/> <xsl:param name="curRow"/> <xsl:param name="numberFormat"/> <!-- Handle this row --> <fo:table-row> <xsl:call-template name="processTableRow"> <xsl:with-param name="itemNode"> <xsl:value-of select="$itemNode"/> </xsl:with-param> <xsl:with-param name="rows"> <xsl:value-of select="$rows"/> </xsl:with-param> <xsl:with-param name="columns"> <xsl:value-of select="$columns"/> </xsl:with-param> <xsl:with-param name="itemCount"> <xsl:value-of select="$itemCount"/> </xsl:with-param> <xsl:with-param name="curRow"> <xsl:value-of select="$curRow"/> </xsl:with-param> <xsl:with-param name="curCol"> <xsl:value-of select="1"/> </xsl:with-param> <xsl:with-param name="numberFormat"> <xsl:value-of select="$numberFormat"/> </xsl:with-param> </xsl:call-template> </fo:table-row> <!-- If this is not the last row, then bump the row count and recurse --> <xsl:if test="$curRow < $rows"> <xsl:call-template name="startTableRow"> <xsl:with-param name="itemNode"> <xsl:value-of select="$itemNode"/> </xsl:with-param> <xsl:with-param name="rows"> <xsl:value-of select="$rows"/> </xsl:with-param> <xsl:with-param name="columns"> <xsl:value-of select="$columns"/> </xsl:with-param> <xsl:with-param name="itemCount"> <xsl:value-of select="$itemCount"/> </xsl:with-param> <xsl:with-param name="curRow"> <xsl:value-of select="$curRow + 1"/> </xsl:with-param> <xsl:with-param name="numberFormat"> <xsl:value-of select="$numberFormat"/> </xsl:with-param> </xsl:call-template> </xsl:if> </xsl:template> <!-- This is a recursive routine that is called for each column in a table row --> <!-- It is called initially with a curCol value of 1, and then recurses --> <!-- until the last column in the row has been rendered --> <xsl:template name="processTableRow"> <xsl:param name="itemNode"/> <xsl:param name="rows"/> <xsl:param name="columns"/> <xsl:param name="itemCount"/> <xsl:param name="curRow"/> <xsl:param name="curCol"/> <xsl:param name="numberFormat"/> <!-- Calculate the position in the node list that we should operate on --> <xsl:variable name="index"> <xsl:value-of select="$curRow + (($curCol - 1) * $rows)"/> </xsl:variable> <fo:table-cell> <fo:block> <!-- If we are still in bounds, render item value, otherwise we want a nice empty cell --> <xsl:if test="$index <= $itemCount"> <!-- If we have a number format, then render the item number --> <xsl:if test="$numberFormat != ''"> <fo:inline font-weight="bold"><xsl:number format="{$numberFormat}" value="$index"/>. </fo:inline> </xsl:if> <!-- Render the item value --> <xsl:value-of select="*[name()=$itemNode][$index]"/> </xsl:if> </fo:block> </fo:table-cell> <!-- If we haven't reached the end of the row, bump the column count and recurse --> <xsl:if test="$curCol < $columns"> <xsl:call-template name="processTableRow"> <xsl:with-param name="itemNode"> <xsl:value-of select="$itemNode"/> </xsl:with-param> <xsl:with-param name="rows"> <xsl:value-of select="$rows"/> </xsl:with-param> <xsl:with-param name="columns"> <xsl:value-of select="$columns"/> </xsl:with-param> <xsl:with-param name="itemCount"> <xsl:value-of select="$itemCount"/> </xsl:with-param> <xsl:with-param name="curRow"> <xsl:value-of select="$curRow"/> </xsl:with-param> <xsl:with-param name="curCol"> <xsl:value-of select="$curCol + 1"/> </xsl:with-param> <xsl:with-param name="numberFormat"> <xsl:value-of select="$numberFormat"/> </xsl:with-param> </xsl:call-template> </xsl:if> </xsl:template> <xsl:template name="makeTableColumns"> <xsl:param name="count"/> <xsl:param name="width"/> <xsl:if test="$count > 1"> <xsl:call-template name="makeTableColumns"> <xsl:with-param name="count" select="round($count - 1)"/> <xsl:with-param name="width" select="$width"/> </xsl:call-template> </xsl:if> <fo:table-column column-width="{$width}"/> </xsl:template> __________________________________ Do you Yahoo!? Yahoo! Mail - Helps protect you from nasty viruses. http://promotions.yahoo.com/new_mail
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
adding a duration to a date/time, Belkin, Alla | Thread | Numbering - how to exclude "cousin", Glen Little |
adding a duration to a date/time, Belkin, Alla | Date | Numbering - how to exclude "cousin", Glen Little |
Month |