latex中使用biblatex和tabularray生成表格文献表

latex中使用biblatex和tabularray生成表格文献表

这是第三篇关于latex中的表格文献表的文章。
前面介绍过两种方式《latex中生成表格形式的参考文献表》
《latex使用bibmap生成表格形式的参考文献表》
这一篇实际上也是利用biblatex生成,但利用新的与一般表格宏包不同的tabularray,有其特殊性,所以做专门的介绍,顺便记录实现的研究过程。

因为tabularray对于表格内容展开的特殊性要求,加上biblatex也只在latex运行时生成文献格式信息(而不是像bibtex,bibmap一样提前生成字符串列表可以直接读取),
所以两者的结合会明显不同于一般情况。下面的尝试和实现,正是考虑了两者的特点。

tabularray的特点

tabularray是先提取表格内容(先展开的),然后再根据内容拆分,做格式化。
而不像其它表格宏包,是按正常顺序展开的。
所以在表格生成过程中,如果有一些包含列标识符的命令,通常需要先展开。比如:

\newcommand*\tblrbody{
\hline
20 & 30 \\
50 & 60 \\
\hline
}

%采用如下这些方式定义表格内容也都可以使用
%\def\tblrbody
%\newrobustcmd{\tblrbody}
%\tl_new:N \l_tblrbody_tl
%\tl_set:Nn \l_tblrbody_tl
%\cs_new:Nn \tblrbody:

\begin{longtblr}[label=none,expand=\tblrbody]
    {colspec = {|Q[c,m,0.10\textwidth]|Q[l,m,0.84\textwidth]|},hlines,
    rowhead = 1,rows={ht=1cm}}
    {\songti 序号 } & {\songti 文献目录(作者、题目、刊物名、出版时间、页次)} \\
    \tblrbody
  \end{longtblr}

其中,\tblrbody要先展开,否则在tex过程中,\tblrbody和longtblr环境会同时展开,就会出现问题。
而加上expand=\tblrbody选项就是让其先展开。

利用biblatex生成表格文献表的尝试

利用biblatex生成表格,使用longtable等表格宏包是没有问题的。

但使用tabularray 就会有问题,因为 tabularray 上述特点。

因此,我们做了尝试,详见 how to build tabular bibliography with tabularray rather than other tabular package

得出的结论是:

  1. 如果在 \extblxtab@bibtabular 中,放入 tblr表,同时利用 newcommand 将biblatex的处理内容收集起来,作为tblr表格的内容,则可以生成表格,但所有的条目都是最后一个条目的信息。也就是在记录到newcommand过程中,一个关键的entrykey信息是没有被确定出来,所以在最后生成的时候,都替换为了最后一条。也就是每个条目的信息,在处理内容存储时是没有充分展开的。

  2. 所以我们希望对其先进行展开,比如利用edef等展开当前条目的内容,然后再收集。但显然biblatex的宏不能完全展开,所以出现了问题。

  3. 所以我们希望尝试是否有其他展开手段,比如将每个条目的内容写入文件。经尝试,也会面临与edef相同的问题。

因为 biblatex-ext-tabular 的作者没有时间看,没有得到有效的提示信息,所以继续思考和尝试,好在最后成功了。详见后续各节。

考虑entrykey展开的实现

根据前面尝试的结论,我们知道导致文献表没有正确生成的原因主要是宏的展开问题,但完全展开又不可能,所以我们考虑是否能做一定的展开,只要展开到能显式地给出entrykey信息就可以了。

我们考察了expandafter等相关的展开命令,以及 biblatex-ext-tabular 中 \extblxtab@bibtabular 等中使用\anchor等宏,发现并不方便利用expandafter等做展开。

于是再考察\anchor等宏的定义,发现其内部使用了\extblxtab@tab@item@anchor{\extblxtab@tabrow@entrykey},而\extblxtab@tabrow@entrykey又是由
\gdef\extblxtab@tabrow@entrykey{##1}定义。所以在输出的时候,实际上存在多次的展开才能到##1。这可能就是需要解决的问题。

所以,既然不能使用expandafter等做提前展开,那么我们可以考虑减少展开的层级,从而等价于提前展开。

因此,我们在\extblxtab@bibtabular 中不再使用\anchor等高层的命令,而使用其内部定义从而减少展开,使得entrykey信息可以提前展开并记录下来。

因此,我们的方式是将原始的:

\def\do##1{%
    \blx@setdefaultrefcontext{##1}%
    \gdef\extblxtab@tabrow@entrykey{##1}%
    \csuse{extblxtab@tabrow@format@\blx@theenv}}%
  \csuse{extblxtab@env@\blx@theenv}%
  \dolistloop{\blx@tempb}%
  \csuse{extblxtab@endenv@\blx@theenv}%

替换为:

  \newcommand\blxtablecontents{}
  \def\do##1{%
    \blx@setdefaultrefcontext{##1}%
    \gdef\extblxtab@tabrow@entrykey{##1}%
    \g@addto@macro\blxtablecontents{\leavevmode\anchor{\printfield{labelnumber}} & \driver{} \\}
    }%
  \dolistloop{\blx@tempb}

再改进为:

  \newcommand\blxtablecontents{} %利用\blxtablecontents来存储文献的信息
  \def\do##1{%
    \blx@setdefaultrefcontext{##1}%
    %不在使用\extblxtab@tabrow@entrykey因为多重定义会导致展开延迟
    %所以导致文献表中的所有文献的信息会被最后一个文献的信息替代
    %\gdef\extblxtab@tabrow@entrykey{##1}%
    %使用\g@addto@macro在\blxtablecontents添加信息
    %同时利用\anchor等的原始定义直接给出entrykey的信息##1
    %而不用extblxtab@tabrow@entrykey避免延迟展开的问题。
    \g@addto@macro\blxtablecontents{ {\leavevmode\extblxtab@tab@item@anchor
                    {##1}{\printfield{labelnumber}}}
    & {\extblxtab@tab@item@driver
                    {##1}{}} \\}
    }%
  \dolistloop{\blx@tempb}%

利用tabularray和biblatex的表格式参考文献表的完整实现

根据上述处理,相当于在展开过程中减少了2层,所以有可能在展开时就能将各个文献条目的entrykey确定下来,从而能避免出错。
结果也验证了这一点。

一个完整的示例如下:

\documentclass{ctexart}
\usepackage[style=gb7714-2015]{biblatex}
\usepackage{biblatex-ext-tabular}
\usepackage{tabularray}
\SetTblrTemplate{head,foot}{empty}

\makeatletter
% underlying macros
\def\extblxtab@bibtabular#1{%
  \blx@bibheading\blx@theheading\blx@thetitle
  \blx@bibnote\blx@theprenote
  \begingroup
  \blx@bibinit
  \let\@noitemerr\@empty
  \let\blx@noitem\blx@warn@bibempty
  \ifnum\bibinitsep=\z@
    \let\blx@initsep\relax
  \fi
  \ifnum\bibnamesep=\z@
    \let\blx@namesep\relax
  \fi
  \csuse{blx@hook@bibinit}%
  \csuse{blx@hook@bibinit@next}%
  % copy filtered list of entries to internal list macro
  \let\blx@tempb\@empty
  \def\blx@do##1{%
    \blx@ifdata{##1}{%
      \begingroup
      \blx@getdata{##1}%
      \blx@bibcheck
      \iftoggle{blx@skipentry}{}{%
        \global\let\blx@noitem\@empty
        \listgadd\blx@tempb{##1}}%
      \endgroup}{}}%
  \let\blx@done\relax
  \blx@listloop{#1}%
  \begingroup
  % sane names for wrapper macros
  \def\plain     {\extblxtab@tab@item@plain
                    {\extblxtab@tabrow@entrykey}}%
  \def\plainlang {\extblxtab@tab@item@plainlang
                    {\extblxtab@tabrow@entrykey}}%
  \def\anchor    {\extblxtab@tab@item@anchor
                    {\extblxtab@tabrow@entrykey}}%
  \def\anchorlang{\extblxtab@tab@item@anchorlang
                    {\extblxtab@tabrow@entrykey}}%
  \def\driver    {\extblxtab@tab@item@driver
                    {\extblxtab@tabrow@entrykey}}%
  % tabular output for each item in list
  % note that each cell is in its own group, hence we need \gdef to
  % break out of the first cell as soon as the row format has a & in it
  % since the assignment will be counted as being in the first cell
  \newcommand\blxtablecontents{} %利用\blxtablecontents来存储文献的信息
  \def\do##1{%
    \blx@setdefaultrefcontext{##1}%
    %不在使用\extblxtab@tabrow@entrykey因为多重定义会导致展开延迟
    %所以导致文献表中的所有文献的信息会被最后一个文献的信息替代
    %\gdef\extblxtab@tabrow@entrykey{##1}%
    %使用\g@addto@macro在\blxtablecontents添加信息
    %同时利用\anchor等的原始定义直接给出entrykey的信息##1
    %而不用extblxtab@tabrow@entrykey避免延迟展开的问题。
    \g@addto@macro\blxtablecontents{ {\leavevmode\extblxtab@tab@item@anchor
                    {##1}{\mkgbnumlabel{\printfield{labelnumber}}}}
    & {\extblxtab@tab@item@driver
                    {##1}{}} \\}
    }%
  \dolistloop{\blx@tempb}%
  %注意表格的格式直接写
  \begin{longtblr}[label=none,expand=\blxtablecontents]
    {colspec = {|Q[c,m,0.10\textwidth]|Q[l,m,0.84\textwidth]|},
    hlines, rowhead = 1,rows={ht=1cm}}
    {\songti 序号 } & {\songti 文献目录(作者、题目、刊物名、出版时间、页次)} \\
    \blxtablecontents
  \end{longtblr}
  %不再使用原来的环境定义来输出表格
  %\csuse{extblxtab@env@\blx@theenv}%
  %\dolistloop{\blx@tempb}%
  %\csuse{extblxtab@endenv@\blx@theenv}%
  \endgroup
  \blx@bibnote\blx@thepostnote
  \endgroup
  \endgroup % this closes the group opened by \printbibtabular
}
\makeatother


\begin{filecontents}[force]{\jobname.bib}
@book{brooks2000,
  title = {Troubling {{Confessions}}: Speaking {{Guilt}} in {{Law}} and {{Literature}}},
  author = {Brooks, Peter},
  date = {2000},
  publisher = {{University of Chicago Press}},
  location = {{Chicago}}
}

@article{chamberlain_SearchCivilSociety_1993,
  title = {On the {{Search}} for {{Civil Society}} in {{China}}},
  author = {Chamberlain, Heath B.},
  date = {1993-04},
  volume = {19},
  number = {2},
  pages = {199--215}
}

@incollection{duwei*fokema_ZouXiangXinShiJieZhuYi_1999,
  title = {走向新世界主义},
  booktitle = {全球化与后殖民批评},
  author = {杜威·佛克马},
  editor = {王宁 and 薛晓源},
  date = {1999},
  pages = {247--266},
  publisher = {中央编译出版社},
  location = {北京}
}

@thesis{fangmingdong_LuoLongJiZhengZhiSiXiangYanJiu19131949_2000,
  type = {博士},
  title = {罗隆基政治思想研究(1913—1949)},
  author = {方明东},
  date = {2000},
  institution = {北京师范大学历史系},
  location = {北京}
}

@incollection{schfield_ImpactScarcityPlenty_1983,
  title = {The {{Impact}} of {{Scarcity}} and {{Plenty}} on {{Population Change}} in {{England}}},
  booktitle = {Hunger and {{History}}: The {{Impact}} of {{Changing Food Production}} and {{Consumption Pattern}} on {{Society}}},
  author = {Schfield, R. S.},
  editor = {Rotberg, R. I. and Rabb, T. K.},
  date = {1983},
  pages = {55--88},
  publisher = {{Cambridge University Press}},
  location = {{Cambridge, MA}}
}

@book{shitenghuixiu_ZhongGuoRenLiuXueRiBenShi_1982,
  title = {中国人留学日本史},
  author = {实藤惠秀},
  translator = {谭汝谦 and 林启彦},
  date = {1982},
  publisher = {香港中文大学出版社},
  location = {香港}
}

@article{weiliying1990,
  title = {论近代西北人口波动的主要原因},
  author = {{魏丽英}},
  date = {1990},
  journaltitle = {社会科学},
  number = {6}
}
\end{filecontents}

\addbibresource{\jobname.bib}

\begin{document}

\nocite{*}

\printbibtabular

\end{document}

其结果为:
在这里插入图片描述

因此:使用biblatex和tabularray生成表格式文献表的方法,总结如下:

  1. 不再使用biblatex-ext-tabular提供的外部接口\defbibtabular{bibtabular}
  2. 直接重定义\extblxtab@bibtabular宏,并在内部做修改,修改内容包括三个部分:
    • 利用新定义的\blxtablecontents来存储文献信息,且展开后作为表格的内容。
    • 重定义\do使得对于entrykey的展开少几层,使得\blxtablecontents展开时能获得对应的entrykey避免出错。
    • 直接添加tblr表格用于输出文献表。
  3. 正文中,正常的引用和输出,输出仍然使用\printbibtabular命令。

小结

本文经过实践和研究,实现了基于biblatex结合tabularray的表格式文献表,在之前的两种方法基础上提供了一种新的路径,方便用户选择使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值