TeX - LaTeX Asked by innisfree on March 20, 2021
Is there a general solution for parsing document author data (name, address, email etc)? I am imagining something like
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
Programming it myself is a bit beyond me, but it seems like it would be very useful. At the moment, I am using lots of different document classes, each with there own idiosyncratic way of parsing author data.
I propose two solutions based on datatool
.
The first requires an external database1.csv
file (in the mwe below it is produced by the filecontents
environment). The second solution creates the database (named database2
) directly in the .tex file through the commands:
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}
The command getauhor
extracts from the line given as the first argument the value given in the second argument:
newcommand{getauthor}[2]{%
DTLforeach*[DTLiseq{num}{#1}]
{database1}%database label
{num=num,email=email,address=address,other=other,name=name}% assignment
{csname#2endcsname}
}
Here is a minimal working example:
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#2endcsname}}
}
%--------------------------------------------------
%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#2endcsname}}
}
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}
Answered by Ivan on March 20, 2021
This can be done for example with expl3's property lists – I changed the syntax a little bit requiring some author ID instead of implying an incremented number (which could be realised as well, of course):
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}
Just for fun let's abuse acro
as an alternative “solution”. Although this is not a completely serious suggestion it could be used quite safely, actually:
documentclass{article}
usepackage{acro}
DeclareAcroProperty{name}
DeclareAcroProperty{email}
DeclareAcroProperty{address}
DeclareAcroProperty{other}
newcommandaddauthor[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}
Answered by cgnieder on March 20, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP