This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Transformation for FO table widths
- From: Gustaf Liljegren <gustaf dot liljegren at xml dot se>
- To: xsl-list at lists dot mulberrytech dot com
- Date: Mon, 29 Apr 2002 19:29:56 +0200
- Subject: [xsl] Transformation for FO table widths
- Reply-to: xsl-list at lists dot mulberrytech dot com
Here's a pretty complex transformation problem.
I have a document type that uses a subset of HTML 3.2 for tables (due to a
limitation in my XML editor). Each TH and TD may have a WIDTH attribute,
that I intend to map to the common width attribute in FO. I know the real
way in XSL is to use fo:table-column with column-width, but due to another
limitation in my FO engine, I can't. Fortunately, the width attribute in FO
seem to work on table-cells too.
I want to use WIDTH attributes only on the *first* row in a table, and all
values should be written in percent in the FO. The rows can be set both in
percent and *pixels* in the XML editor. There may also be elements without
WIDTH attributes. Currentlt, I don't handle these at all. Here's an example
with both percent and pixel values:
30% 400 50 10%
The original percent values are transfered directly to the FO. Pixel nodes
are converted to percent nodes with a long mathematical expression. The
problems seem to start when I sum up percent values and pixel values in two
node-sets:
<!-- Match the first row in any table -->
<xsl:template match="TR[1]">
<fo:table-row>
<xsl:if test="TH/@WIDTH | TD/@WIDTH">
<!-- Get @WIDTH-nodes with percent values -->
<xsl:variable name="percent-nodes">
<xsl:value-of select="TH[contains(@WIDTH, '%')] |
TD[contains(@WIDTH, '%')]"/>
</xsl:variable>
There's a similar variable for pixel values. I guess there's something
wrong with my use of the contains() function. Another approach I've tried
is this:
<xsl:variable name="percent-nodes">
<xsl:for-each select="TH | TD">
<xsl:if test="contains(@WIDTH, '%')">
<xsl:value-of select="@WIDTH"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
But this code will only get the first percent node. What I do next is to
sum up these values, like this:
<!-- Sum up percent values -->
<xsl:variable name="percent-sum"
select="sum(number(substring-before($percent-nodes, '%')))"/>
<!-- Sum up pixel values -->
<xsl:variable name="pixelsumma"
select="sum(number($pixel-nodes))"/>
Finally, here's the code that constructs the table cells:
<xsl:for-each select="TH | TD">
<fo:table-cell>
<xsl:choose>
<xsl:when test="contains(@WIDTH, '%')">
<xsl:attribute name="width">
<xsl:value-of select="@WIDTH"/>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="width">
<xsl:value-of select="number(@WIDTH) *
(100 - $percent-sum) div (100 * $pixel-sum)"/>
</xsl:attribute>
<xsl:otherwise>
</xsl:choose>
<fo:block>
<xsl:apply-templates/>
</fo:block>
</fo:table-cell>
</xsl:for-each>
That's all.
Gustaf
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list