是否有一个通用的解决方案来解析文档作者数据(姓名、地址、电子邮件等)?我设想的是
\documentclass{whatever}
\addauthor[email = ..., address = ..., other = ..., name = Alice]
\addauthor[email = ..., address = Bob's address, other = ..., name = Bob]
% Now I retrieve it however I want to create a title page
\getauthor{1}{name} % gives Alice
\getauthor{2}{address} % gives Bob's address
自己编写程序有点超出我的能力,但看起来很有用。目前,我正在使用许多不同的文档类,每个类都有自己独特的解析作者数据的方式。
答案1
我提出了两种基于 的解决方案datatool
。第一种需要外部database1.csv
文件(在下面的 mwe 中,它由环境生成)。第二种解决方案通过以下命令直接在 .tex 文件中filecontents
创建数据库(名为):database2
\DTLnewdb{database2}
\newcommand{\addauthor}[5]{
\DTLnewrow{database2}%
\DTLnewdbentry{database2}{num}{#1}
\DTLnewdbentry{database2}{email}{#2}
\DTLnewdbentry{database2}{address}{#3}
\DTLnewdbentry{database2}{other}{#4}
\DTLnewdbentry{database2}{name}{#5}
}
\addauthor{1}{email1}{Alice's address}{other1}{Alice}
\addauthor{2}{email2}{Bob's address}{other2}{Bob}
\addauthor{3}{email3}{Markus's address}{other3}{Markus}
该命令\getauhor
从第一个参数给出的行中提取第二个参数给出的值:
\newcommand{\getauthor}[2]{%
\DTLforeach*[\DTLiseq{\num}{#1}]
{database1}%database label
{\num=num,\email=email,\address=address,\other=other,\name=name}% assignment
{\csname#2\endcsname}
}
这是一个最小的工作示例:
\documentclass{book}
\usepackage{datatool}
%--------------------------------------------------
% First method
%--------------------------------------------------
\begin{filecontents}[overwrite]{database1.csv}
num,email,address,other,name
1,email1,Address 1,Other 1, Isaak Bacharach
2,email2,Address 2,Other 2, Reinhold Baer
3,email3,Address 3,Other 3, Christian Bär
4,email4,Address 4,Other 4, Wolf Barth
\end{filecontents}
\DTLloaddb{database1}{database.csv}
\newcommand{\getauthor}[2]{%
\DTLforeach*[\DTLiseq{\num}{#1}]
{database1}%database label
{\num=num,\email=email,\address=address,\other=other,\name=name}% assignment
{\textbf{\csname#2\endcsname}}
}
%--------------------------------------------------
%Second method
%--------------------------------------------------
\DTLnewdb{database2}
\newcommand{\addauthor}[5]{
\DTLnewrow{database2}%
\DTLnewdbentry{database2}{num}{#1}
\DTLnewdbentry{database2}{email}{#2}
\DTLnewdbentry{database2}{address}{#3}
\DTLnewdbentry{database2}{other}{#4}
\DTLnewdbentry{database2}{name}{#5}
}
\addauthor{1}{email1}{Alice's address}{other1}{Alice}
\addauthor{2}{email2}{Bob's address}{other2}{Bob}
\addauthor{3}{email3}{Markus's address}{other3}{Markus}
\newcommand{\GetAuthor}[2]{%
\DTLforeach*[\DTLiseq{\num}{#1}]
{database2}%database label
{\num=num,\email=email,\address=address,\other=other,\name=name}% assignment
{\textbf{\csname#2\endcsname}}
}
\begin{document}
\section{First method (\texttt{database1.csv})}
The name of the forth entry is \getauthor{4}{name}\\
The address of the second entry is \getauthor{2}{address}
\section{Second method (\texttt{database2})}
The name of the first entry is \GetAuthor{1}{name}\\
The address of the second entry is \GetAuthor{2}{address}
\end{document}
答案2
例如,可以使用 expl3 的属性列表来实现这一点——我稍微改变了语法,需要一些作者 ID,而不是暗示一个递增的数字(当然也可以实现):
\documentclass{article}
\ExplSyntaxOn
\tl_new:N \l__innisfree_author_tl
\cs_new_protected:Npn \innisfree_add_author:nn #1#2
{
\prop_if_exist:cF {l__innisfree_author_#1_prop}
{ \prop_new:c {l__innisfree_author_#1_prop} }
\tl_set:Nn \l__innisfree_author_tl {#1}
\keyval_parse:NNn
\__innisfree_value_missing:n
\__innisfree_set_property:nn
{#2}
}
\cs_set_protected:Npn \__innisfree_value_missing:n #1
{ \prop_put:cnn {l__innisfree_author_ \l__innisfree_author_tl _prop} {#1} {??} }
\cs_set_protected:Npn \__innisfree_set_property:nn #1#2
{ \prop_put:cnn {l__innisfree_author_ \l__innisfree_author_tl _prop} {#1} {#2} }
\cs_new:Npn \innisfree_get_author:nn #1#2
{ \prop_item:cn {l__innisfree_author_#1_prop} {#2} }
\NewDocumentCommand \addauthor {mm}
{ \innisfree_add_author:nn {#1} {#2} }
\NewDocumentCommand \getauthor {mm}
{ \innisfree_get_author:nn {#1} {#2} }
\ExplSyntaxOff
\addauthor{a}{email = ..., address = ..., other = ..., name = Alice}
\addauthor{b}{email = ..., address = Bob's address, other = ..., name = Bob}
\begin{document}
\getauthor{a}{name} \par
\getauthor{b}{address}
\end{document}
只是为了好玩,让我们滥用它acro
作为替代“解决方案”。虽然这不是一个完全严肃的建议,但实际上它可以相当安全地使用:
\documentclass{article}
\usepackage{acro}
\DeclareAcroProperty{name}
\DeclareAcroProperty{email}
\DeclareAcroProperty{address}
\DeclareAcroProperty{other}
\newcommand\addauthor[2]{%
\DeclareAcronym{#1}{
short = #1 , long = #1 , #2 ,
tag = authors % a filter to separate them from ``real'' acronyms – not
% really necessary
}%
}
\newcommand*\getauthor[2]{\acrofield{#1}{#2}}
\addauthor{a}{email = ..., address = ..., other = ..., name = Alice}
\addauthor{b}{email = ..., address = Bob's address, other = ..., name = Bob}
\begin{document}
\getauthor{a}{name} \par
\getauthor{b}{address}
\end{document}