3

Background

Style an XHTML table footer for the last row, provided a tfoot element isn't already present.

Code

Given:

\startbuffer[document]
<table>
<thead>
<tr><th>Item</th><th>Power</th><th>Usage</th><th>Cost</th></tr>
</thead>
<tbody>
<tr><td>Geothermal</td><td>1250</td><td>Electricity</td><td>5.1</td></tr> 
<tr><td>Fire Station</td><td>-9.6</td><td>Protection</td><td>0.5</td></tr> 
<tr><td>Roads</td><td>0</td><td>Transport</td><td>0.9</td></tr> 
<tr><td>Totals</td><td>129.9</td><td>n/a</td><td>19.4</td></tr> 
</tbody></table> 
\stopbuffer

\xmlregistersetup{xml:xhtml}
\startxmlsetups xml:xhtml
  \xmlsetsetup{\xmldocument}{*}{-}
  \xmlsetsetup{\xmldocument}{table|thead|tbody|tfoot|tr|th|td|caption}{xml:*}
\stopxmlsetups

\startxmlsetups xml:table
  \startembeddedxtable\xmlflush{#1}\stopembeddedxtable
\stopxmlsetups
\startxmlsetups xml:thead
  \startxtablebody[head]\xmlflush{#1}\stopxtablebody
\stopxmlsetups
\startxmlsetups xml:tbody
  \startxtablebody[body]\xmlflush{#1}\stopxtablebody
\stopxmlsetups
\startxmlsetups xml:tfoot
  \startxtablebody[foot]\xmlflush{#1}\stopxtablebody
\stopxmlsetups
\startxmlsetups xml:tr
  \startxrow\xmlflush{#1}\stopxrow
\stopxmlsetups
\startxmlsetups xml:th
  \startxcell\bold{\xmlflush{#1}}\stopxcell
\stopxmlsetups
\startxmlsetups xml:td
  \startxcell\xmlflush{#1}\stopxcell
\stopxmlsetups

\setupxtable[
  frame=off,
  topframe=on,
  bottomframe=on,
  option={stretch,width},
  split=yes,
  header=repeat,
  footer=repeat,
]

\setupxtable[head][rulethickness=1pt]
\setupxtable[body][]
\setupxtable[foot][rulethickness=1pt]

\starttext\xmlprocessbuffer{}{document}{}\stoptext

Produces:

Table Output

Problem

The footer row is not recognized, which means the following style isn't applied:

\setupxtable[foot][rulethickness=1pt]

In some cases, the XHTML table includes a tfoot element; in other cases, the XHTML table does not have a tfoot. In both situations, the footer xtable setup must be applied (i.e., set the rule thickness for [foot]).

Attempts

The following nearly works, but the last row is not added to the table:

\xmlsetsetup{\xmldocument}{tr[position()<last()]}{xml:tr}
\xmlsetsetup{\xmldocument}{tr[position()=last() and ../name()='tbody']}{xml:tr:foot}
\xmlsetsetup{\xmldocument}{tr[position()=last() and ../name()='tfoot']}{xml:tr}

% ... other setups ...

\startxmlsetups xml:tr:foot
  \startxtablebody[foot]\startxrow\xmlflush{#1}\stopxrow\stopxtablebody
\stopxmlsetups

Question

How would you style the last table row when the table doesn't contain a tfoot element, such that the styling doesn't conflict when a tfoot element is present?

To clarify, in XSL the logic would resemble:

<!-- Not last row -or- is the last row but not in the footer -->
<xsl:template match="tr[not(last())] or (tr[last()] and ../tfoot)">
  \startxrow\xmlflush{#1}\stopxrow
</xsl:if>

<!-- Last row and not in the footer -->
<xsl:template match="tr[last()] and not(../tfoot)">
  \startxtablebody[foot]
    \startxrow\xmlflush{#1}\stopxrow
  \stopxtablebody
</xsl:template>

<!-- Always apply the footer when it exists -->
<xsl:template match="tfoot">
  \startxtablebody[foot]\xmlflush{#1}\stopxtablebody
</xsl:template>

ConTeXt version: 2021.03.31 18:04

2
  • Remove the closing body from the xml:tbody setups.
  • Introduce specific tr definitions for not last and last.
  • Close the xml:tbody within the last tr.

In code:

\startxmlsetups xml:xhtml
  \xmlsetsetup{\xmldocument}{*}{-}
  \xmlsetsetup{\xmldocument}{table|thead|tbody|tfoot|th|td|caption}{xml:*}
  \xmlsetsetup{\xmldocument}{tr[position()!=last()]}{xml:tr}
  \xmlsetsetup{\xmldocument}{tr[position()=last()]}{xml:tr:last}
\stopxmlsetups

\startxmlsetups xml:tbody
  \startxtablebody[body]
    \xmlflush{#1}
\stopxmlsetups

\startxmlsetups xml:tr:last
  \stopxtablebody
  \startxtablebody[foot]
  \startxrow\xmlflush{#1}\stopxrow
  \stopxtablebody
\stopxmlsetups

This is a bit brittle.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.