我在尝试用 LaTeX 以语义方式标记表格时遇到了问题。
背景
要么是标准的,要么是\hline
和来自(我认为)或和来自推荐的视觉结构表格(或更确切地说是表格)。但它们并不是真正的语义标记。为此,人们会像在 HTML 中分别使用、和 来标识页眉、页脚和(可能多个)正文。\firsthline
\lasthline
array.sty
\midrule
\toprule
\bottomrule
booktabs.sty
<thead>
<tfoot>
<tbody>
页眉和页脚都不应与标题混淆,但在 LaTeX 中,这种情况不太可能发生,因为有一个直观命名的宏\caption
,并且默认情况下它只适用于浮动表,这是理所当然的。页脚也不是本地脚注的位置(参见的第二个强制参数\ctable
或tablenotes
中的环境threeparttable.sty
)。相反,页脚通常包含带有列总和等的行。页眉通常在其单元格中包含列标签,这些标签可以按层次结构排列在多行上。
最左边和最右边的列可能具有与最顶部和最底部行类似的作用,但由于 LaTeX(如 HTML)中的表格首先垂直排列,因此很难编码。尽管如此,由于列的定义方式是强制性的,因此将tabular
一些样式应用于列中的所有单元格实际上比应用于行中的单元格更容易。在 HTML+CSS 中则相反。
有时,您希望相同的表格在两种设置中看起来截然不同,例如,投影仪演示文稿 ( \mode<presentation>
) 及其讲义 ( \mode<article>
)。因此,在语义上对其进行标记并指定每种模式的样式是有意义的。我问过这个问题tabular
beamer
根据booktabs
标记将样式设置为块,但没有得到答复。
问题
- 我应该使用哪种标记(在下面描述的标记中)?
- 我如何使用环境而不是命令来实现这一点?
恐怕 1. 的答案是“环境”(即最后的变体),但同时 2. 的答案是“你不能”。
修补表格环境
\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}
这种简单的方法有效,但没有显示出太多明确的语义。
语义表部分作为开关
\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}
这种别名确实“有效”,但需要额外的命令\tEnd
。这似乎是错误的。
使用tabular
语义表部分作为开关进行修补
\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}
该方法将上面描述的两种方法结合起来,从而解决了\tEnd
。
语义表部分作为具有单个参数的宏
\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}
这确实有效,但是命令可以接收很长的参数,因此很容易忘记结束的花括号或它所属的内容。
具有多个参数的单表宏
\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}
这仅允许单个表体。
语义表部分作为环境
\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}
这是我喜欢的方法,但它不起作用,我不知道具体原因。 内部环境tabular
,尤其是当它们包含多个单元格或(如本例)甚至行时,通常看起来有问题。 这就是我问问题 2 的原因。
答案1
表格单元格就像一个组,这就是为什么字体更改等仅适用于一个单元格,
\begin{tabular}{lll}a&b&c\end{tabular}
就好像
{a}{b}{c}
其中每个组实际上都是一个特殊的对齐“未设置框”结构,但对于大多数其他目的而言,它就像一个普通组一样工作。
所以你的环境最终看起来像
{\begin{thead} Header }{ Header}{ \end{thead}}
正如您所见,组嵌套完全错误,因为结束环境与开始环境不在同一组中。
可以使用\begin
\end
语法,但只能通过本地重新定义\begin
和\end
(以及大多数 latex 表格机制)。这使得代码相当脆弱且与其他所有内容不兼容,但您可以查看包blkarray
以实现此想法。但是对于真正的生产文档,我不会使用blkarray
它,它更像是一个实现草图而不是生产代码(并且已经这样超过 20 年了:-)