TransWikia.com

Package for parsing author data

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.

2 Answers

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}

enter image description here


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

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP