0

I have an entry key foo in my (biblatex-biber managed) bibliography, with a crossref field pointing to another entry key. To automate type-setting operations on a series of files, I would like to be able to cite the cross-referenced entry with something like: \citefull{\citefield{foo}{crossref}}

This naive syntax does not work, as biblatex commands are not nestable/expandable. Any hints on how to proceed?

Bonus, that could be handy too: \citefull[\citefield{foo}{note}]{\citefield{foo}{crossref}}

What I've tried: Many posts mention this nesting/expanding limitation and propose a workaround. I thus know this is somehow possible, but I don't understand the codes well enough to adapt them to my needs. For example this question seems quit closely related. The closest that I got was tweaking this answer, which is supposed to be more complex that what I need, as it deals with name list and I only want to expand a monolithic field. My tweak below does print the full reference of key num3 when calling key num4 (whose author field contains num3) like I want it to. However, I was not able to call the crossref field (nor a custom verba field) instead of the author field.

\documentclass{article}                                                      
\usepackage[american]{babel}                                                 
\usepackage[backend=biber,firstinits]{biblatex}                              

\usepackage{filecontents}                                                    
\begin{filecontents}{\jobname.bib}                                           
@misc{num03,                                                                 
title = {Title XX3},                                                         
author = {Author2 Authorsen2 and Author2a Authorsen2a},                      
}                                                                            
@misc{num04,                                                                 
title = {Title},                                                             
author = {num03},                                                            
verba = {num03},                                                             
crossref = {num03},                                                          
}                                                                            
\end{filecontents}                                                           
\addbibresource{\jobname.bib}                                                

\newcommand*{\name}{}                                                        
\DeclareIndexNameFormat{getname}{%                                           
\nameparts{#1}                                                               
\ifblank{\namepartgiveni}                                                    
  {}                                                                         
  {\iffirstinits                                                             
     {\xappto{\name}{\namepartgiveni\space}}                                 
     {\xappto{\name}{\namepartgiven\space}}}%                                
\ifblank{\namepartprefix}                                                    
  {\xappto{\name}{\namepartfamily}}                                          
  {\xappto{\name}{\namepartprefix\space\namepartfamily}}}                    
\DeclareCiteCommand{\getauthor}                                              
  {\undef\name                                                               
   \boolfalse{citetracker}%                                                  
   \boolfalse{pagetracker}}                                                  
  {\ifnameundef{author}                                                      
     {}                                                                      
     {\ifboolexpr{ test {\ifnumgreater{\value{citecount}}{1}}                
                   and not test {\ifundef{\name}} }                          
        {\gappto{\name}{; }}                                                 
        {}%                                                                  
      \indexnames[getname][1-99]{author}}}                                   
  {}                                                                         
  {}                                                                         

\begin{document}                                                             
\getauthor{num04}                                                            
\fullcite{\name}                                                             
\end{document}                                                               

Which, after the correct pdflatex/biber runs, gives: result

I also have another (ugly) workaround based on an execute field containing a \nocite{num03}. I then tweak printbilbiography and it kind of goes the way I need... But it really doesn't sound like a proper way of doing this!

letax
  • 41
  • Could you please add an example (with your already existing entries) what you want to see in the end? – Venez Mar 31 '20 at 10:22
  • I've edited the post to include the output of the example I give. It already gives what I want to get in the end. – letax Mar 31 '20 at 10:49

1 Answers1

1

Unfortunately, the way entry data is saved in biblatex means we can't expandably get hold of field values (which is a bit of a bummer), so we will have to work with helper macros that hold the field value.

\makeatletter
% {<command>}{<entrykey>}{<field>}
\newcommand*{\getfieldinto}[3]{%
  \nocite{#2}%
  \begingroup
  \blx@getdata@cite{#2}%
  \edef\my@tempa{\endgroup
    \def\unexpanded{#1}{%
      \blx@imc@iffieldundef{#3}
        {}
        {\csexpandonce{abx@field@#3}}}}%
  \my@tempa}
\makeatother

Works similar to the code in the question that extracts the name expandably, but works on a field level and is less complicated, because it does not have to deal with the complexities of name handling in biblatex.

\getfieldinto{<command>}{<entrykey>}{<field>}

extracts the contents of <field> for <entrykey> into the macro <command>. So you would use it like

\getfieldinto{\mycomm}{num04}{verba}

to get num04's verba into \mycomm.

The fields crossref and xref that one might intuitive want to use here can't be used because they are special and may not actually make it to the .bbl file (the entry data read by biblatex), so something like verba (or a custom verb field) is probably the safest option.

\documentclass{article}
\usepackage[american]{babel}
\usepackage{csquotes}
\usepackage[backend=biber, giveninits]{biblatex}

\makeatletter
% {<command>}{<entrykey>}{<field>}
\newcommand*{\getfieldinto}[3]{%
  \nocite{#2}%
  \begingroup
  \blx@getdata@cite{#2}%
  \edef\my@tempa{\endgroup
    \def\unexpanded{#1}{%
      \blx@imc@iffieldundef{#3}
        {}
        {\csexpandonce{abx@field@#3}}}}%
  \my@tempa}
\makeatother

\begin{filecontents}{\jobname.bib}
@misc{num03,
  title  = {Title XX3},
  author = {Author2 Authorsen2 and Author2a Authorsen2a},
}
@misc{num04,
  title    = {Title},
  verba    = {num03},
  note     = {note},
}
\end{filecontents}
\addbibresource{\jobname.bib}

\begin{document}
\getfieldinto{\mykey}{num04}{verba}
\getfieldinto{\mynote}{num04}{note}
\fullcite[\mynote]{\mykey}
\end{document}

Expected output.

It is possible to access the entry data of a different entry from within a cite command, so there may well be a way to solve your problem differently (and possibly more elegantly), but for that we would have to know what your actual use case is about.

moewe
  • 175,683
  • I don't have enough reputation to up-vote your very didactic answer... Thanks a lot anyway! I'll accept it as soon I've checked it works all right, and whether I need to edit my question/post a new one. – letax Apr 03 '20 at 10:45
  • Well, it does the job and +1 for providing a generic mean to expand any field, that will definitely be useful. I'm slightly disappointed that I have to repeat the cross-reference key in verba but never mind, it's far better that my previous hacks! – letax Apr 03 '20 at 18:48
  • @letax In principle you could get the crossref field to show in the .bbl at all times by setting mincrossrefs=1, (the default is mincrossrefs=2,), but that has side-effects if you ever really want to use crossref for their intended function. (You can also use a sourcemap to copy crossref to verba automatically. Then you only need the code for the sourcemap and need not copy the fields manually.) – moewe Apr 03 '20 at 18:50
  • Sounds great to automate this! From the doc p197 I tried \DeclareSourcemap{\maps[datatype=biblatex]{\map{\step[fieldsource = crossref] \step[fieldset = verba] }}} which compiles ok but does not work... Should I ask a new question or edit this one? – letax Apr 03 '20 at 19:21
  • @letax You're missing an origfieldval and you can combine the two \steps into one: \DeclareSourcemap{\maps[datatype=bibtex]{\map{\step[fieldsource = crossref, fieldset = verba, origfieldval]}}}. – moewe Apr 03 '20 at 19:26
  • @letax A slightly shorter alternative would be fieldtarget, then we don't need the origfieldval: \DeclareSourcemap{\maps[datatype=bibtex]{\map{\step[fieldsource = crossref, fieldtarget = verba]}}} – moewe Apr 03 '20 at 19:27
  • this works well on the mwe, not in my full document. Working with multiple *bib seems to have no impact... Investigating. – letax Apr 03 '20 at 19:39
  • @letax In case you need to ask more about that I suggest you ask a new question and don't edit this question here. – moewe Apr 03 '20 at 19:42
  • Dumb-old-classical typo... It works perfectly. Thanks again for your help, I learned a lot today! – letax Apr 03 '20 at 19:55