3

I run into issues trying to markup tables semantically in LaTeX.

Background

Either standard \hline together with \firsthline and \lasthline from array.sty (I think) or \midrule, \toprule and \bottomrule from recommended booktabs.sty visually structure tables (or rather tabulars). They’re not truly semantic markup, though. For that, one would identify header, footer and (possibly multiple) bodies as is done in HTML with <thead>, <tfoot> and <tbody> respectively.

Neither header nor footer should be confused with the caption, but in LaTeX that’s unlikely anyhow, because there’s an intuitively named macro \caption for that and it is only available for floating tables by default as it should be. The footer also is not the place for local footnotes (cf. the second mandatory parameter of \ctable or the tablenotes environment in threeparttable.sty). Instead, the footer usually contains rows with column sums and the like. The header most often contains column labels in its cells, which may be arranged hierarchically over several rows.

The left-most and right-most columns may have roles similar to the top-most and bottom-most rows, but since tabulars in LaTeX (like HTML) are arranged vertically first that’s hard to encode. Nevertheless, due to the mandatory way columns are defined with tabular it’s actually easier to apply some styling to all cells in a column than to a cells in a row. It’s the other way around in HTML+CSS.

You sometimes want the same tables to look quite different in two setups, e.g. a beamer presentation (\mode<presentation>) and its handout (\mode<article>). Therefore it makes sense to mark it up semantically and specify the styling per mode. I asked about that in tabular styled like blocks in beamer based upon booktabs markup, but did not get an answer.

Questions

  1. What kind of markup should I use (out of the ones described below)?
  2. How can I do it with environments instead of commands?

I’m afraid the answer to 1. is “environments” (i.e. the final variant), but at the same time the answer to 2. is ”you cannot”.

Patched tabular environment

\documentclass{scrartcl}
\usepackage{booktabs}

\let\oldtabular\tabular
\let\oldendtabular\endtabular
\renewcommand\tabular[1]{\oldtabular{#1}\toprule}
\renewcommand\endtabular{\bottomrule\oldendtabular}
\newcommand\tpart{\midrule}

\begin{document}
\begin{tabular}{ll}
Header & Header \\
\tpart
Body & Body \\ 
Body & Body \\
\tpart
Body & Body \\
\tpart
Footer & Footer \\
\end{tabular}
\end{document}

This simple approach works, but doesn’t show much explicit semantics.

Semantic table parts as switches

\documentclass{scrartcl}
\usepackage{booktabs}

\newcommand{\tHead}{\toprule}
\newcommand{\tFoot}{\midrule}
\newcommand{\tBody}{\midrule}    
\newcommand{\tEnd}{\bottomrule}

\begin{document}
\begin{tabular}{ll}
\tHead
Header & Header \\
\tBody
Body & Body \\ Body & Body \\
\tBody
Body & Body \\
\tFoot
Footer & Footer \\
\tEnd
\end{tabular}
\end{document}

This kind of aliasing does “work”, but requires an additional command \tEnd. This seems just wrong.

Patched tabular with semantic table parts as switches

\documentclass{scrartcl}
\usepackage{booktabs}

\let\oldtabular\tabular
\let\oldendtabular\endtabular
\renewcommand\tabular[1]{\oldtabular{#1}\toprule}
\renewcommand\endtabular{\bottomrule\oldendtabular}
\newcommand{\tHead}{}
\newcommand{\tFoot}{\midrule}
\newcommand{\tBody}{\midrule}    

\begin{document}
\begin{tabular}{ll}
\tHead
Header & Header \\
\tBody
Body & Body \\ Body & Body \\
\tBody
Body & Body \\
\tFoot
Footer & Footer \\
\end{tabular}
\end{document}

This method combines the two described above and thus disposes of \tEnd.

Semantic table parts as macros with single parameters

\documentclass{scrartcl}
\usepackage{booktabs}

\newcommand{\Thead}[1]{\toprule #1 \midrule}
\newcommand{\Tfoot}[1]{#1 \bottomrule}
\newcommand{\Tbody}[1]{#1 \midrule}    

\begin{document}
\begin{tabular}{ll}
\Thead{ Header & Header \\}
\Tbody{ Body & Body \\ Body & Body \\}
\Tbody{ Body & Body \\}
\Tfoot{ Footer & Footer \\}
\end{tabular}
\end{document}

This does work, but the commands can receive very long arguments so it’s easy to lose track of the closing curly brace or what it belongs to.

Single table macros with multiple parameters

\documentclass{scrartcl}
\usepackage{booktabs}

%% \Tabular{header}{body}{footer}
\newcommand{\Tabular}[3]{%
  \toprule #1 \midrule #2 \midrule #3 \bottomrule}


\begin{document}
\begin{tabular}{ll}
\Tabular%
{ Header & Header \\}%
{ Body & Body \\ Body & Body \\}%
{ Footer & Footer \\}
\end{tabular}
\end{document}

This allows only a single table body.

Semantic table parts as environments

\documentclass{scrartcl}
\usepackage{booktabs}

\newenvironment{thead}{\toprule}{\midrule}
\newenvironment{tfoot}{}{\bottomrule}
\newenvironment{tbody}{}{\midrule}

\begin{document}
\begin{tabular}{ll}
\begin{thead} Header & Header \\ \end{thead}
\begin{tbody} Body & Body \\ Body & Body \\ \end{tbody}
\begin{tbody} Body & Body \\ \end{tbody}
\begin{tfoot} Footer & Footer \\ \end{tfoot}
\end{tabular}
\end{document}

This is my preferred approach but it does not work and I don’t know why exactly. Environments inside tabular, especially when they shall contain multiple cells or – as in this case – even rows seem problematic in general. This is why I ask question 2.

1 Answer 1

6

A table cell is like a group, which is why font changes etc only apply to one cell so

\begin{tabular}{lll}a&b&c\end{tabular}

is like

{a}{b}{c}

where each group is actually a special alignment "unset box" structure, but for most other purposes works like a normal group.

So your environments end up looking like

{\begin{thead} Header }{ Header}{ \end{thead}}

and as you can see the group nesting is all wrong as the end environment is not in the same group as the begin.

It is possible to use the \begin \end syntax but only by locally redefining \begin and \end (and most of the latex tabular mechanism. Which makes the code rather fragile and incompatible with everything else, but you can look at the blkarray package for an implementation of this idea. For a real production document though, I wouldn't use blkarray it's more of an implementation sketch than production code (and has been that way for over 20 years:-)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .