2

I would like to know if it is possible in LaTeX to automatise the bibliography.

For example, I would only put the DOI link in the bibliography and latex would take all the info (author, date, title etc).

  • 3
    Probably not impossible with LuaLaTeX, but I would use a reference manager to obtain the bibliographic data from the DOI and write a .bib file from that. It requires a few more steps, but it allows you to tweak the entry data in case the automatically imported data is flawed (it often is). I think JabRef lets you import entries by DOI. – moewe Jun 22 '18 at 7:44
  • 1
    Not really feasible. Database entries like that are often faulty. – Johannes_B Jun 22 '18 at 8:06
6

This answer is proof of concept for creating a bibliography from DOI's by invoking the R package, rcrossref, and its cr_cn function, then using knitr to create a bibliography in LaTeX. (Note well: knitr and rcrossref are R packages and an installation of R is required to proceed).

The cr_cn function pulls publication metadata from the Crossref database, which contains bibliometric data submitted to the Crossref organization by publishers of journals and books. A limitation of this approach is that not all publishers submit their publication data to Crossref. Therefore, passing some DOI's may not return metadata if the relevant metadata has not been submitted by the publisher.

There are various ways of invoking R code together with LaTeX using Sweave or knitr. I used the WinEdt plugin, RManager. Yihui Xie, the author of knitr lists other options here: Editors for knitr. Another option is to use RStudio.

The LaTeX and R code is in a Rnw (R no web) file. The R code chunk appears between delimters <<>>= and @, which signify the start and end of the code chunk. When the .Rnw file is compiled, R is invoked to first execute the R code. This produces a .tex file, and in this case a .bib file. After executing the R code a LaTeX compiler (e.g. PDFLaTeX) can be invoked to generate the .pdf file which contains a formatted bibliography in the style specified to Biblatex.

The R code only requires creation of a list of dois, and a loop to make repeated calls to retrieve the publication metadata from the DOIs that are passed to Crossref. Each metadata item is returned in bibtex format, which is written to a .bib file using R's write.table function.

With the R code executed, LaTeX then uses the generated .bib file (here mybibfile.bib) to create a bibliography using biblatex and biber.

To summarize the sequence of steps: (1) Execute R code to produce .bib file (2) Execute PDFlatex to produce .bcf file, (3) Execute biber to create .bbl file (4) Execute PDFlatex to produce bibliography. RManager in WinEdt executes the sequence automatically.

This is the code:

% knitr -> PDFLaTeX in WinEdt 10.2 with RManager plugin
% http://www.winedt.org/config/modes/RManager.html
\documentclass[a4paper,10pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[margin=2.5cm]{geometry}
\usepackage[style=authoryear,backend=biber]{biblatex}
\addbibresource{mybibfile.bib}

% This is the R code chunk
<<Preamble,include=FALSE>>=
# install the R packages, if they are not already installed.
#install.packages("rcrossref",dependencies=True)
#install.packages("patchDVI",dependencies=True)

# load knitr and rcrossref
library(knitr)
library(rcrossref)

# nominate the DOIs of interest
mydois <- c('10.1002/andp.19053221004',
'10.1038/171737a0',
'10.1038/227680a0',
'10.1103/PhysRevB.37.785')

# extract the metadata for each DOI from Crossref and write the bib file
for(i in 1:4) {
     x <- cr_cn(dois=mydois[i], format = "bibtex")
     write.table(x,file="mybibfile.bib",append=TRUE,row.names=FALSE,col.names=FALSE,fileEncoding="UTF-8")
}
@
% Print the bibliography
\begin{document}
\nocite{*}
\printbibliography
\end{document}

This is the LaTeX output:

enter image description here

5

Answer reworked so that arbitrary entry keys can be assigned to DOI entries.

Here is a proof of concept with LuaLaTeX that queries https://api.crossref.org and downloads the .bib entries to \jobname-doidump.bib. To avoid querying the database more than once for the same entry we remember the keys we asked for in the temporary file \jobname.dol (that means that the two files should not be modified by hand and should be deleted together, the files should be deleted if a DOI-key pair changes).

You can request a DOI at any point with \getdoias{<DOI>}{<entrykey>}. Requested keys can then be cited as usual.

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{csquotes}

\usepackage[style=authoryear, backend=biber]{biblatex}

% externalise lua code, so we don't have to escape stuff
\usepackage{filecontents}
\begin{filecontents*}{doidownload.lua}
function download_to_table(url)
  local texio = texio
  local io = require('io')
  local http = require('socket.http')
  local ltn12 = require('ltn12')
  local requestbody = {}
  texio.write_nl('Downloading ' .. url)
  texio.write_nl('')
  http.request{
    url  = url,
    sink = ltn12.sink.table(requestbody)
  }
  return requestbody
end

-- this function is not used any more, but might still be of interest
function download_to_file_append(url, file_name)
  local io = require('io')
  local requestbody = download_to_table(url)
  local file_handle = io.open(file_name, 'a')
  file_handle:write(table.concat(requestbody))
  file_handle:write('\n')
  file_handle:write('\n')
  io.close(file_handle)
end

function save_doi_as_key_to(doi, key, file_name)
  local texio = texio
  local string = string
  local io = require('io')
  local file_handle = io.open(file_name, 'a')
  local bibentry_tab = download_to_table('https://api.crossref.org/works/' ..
                                         doi .. '/transform/application/x-bibtex')
  local bibentry_str = table.concat(bibentry_tab)
  if string.match(bibentry_str, '^%s*@.-{.-,') then
    bibentry_str = string.gsub(bibentry_str, '^%s*@(.-){.-,', '@%1{' .. key .. ',', 1)
    file_handle:write(bibentry_str)
    file_handle:write('\n')
    file_handle:write('\n')
  else
    texio.write_nl('Warning: Failed to obtain valid bib entry for ' .. key)
    texio.write_nl('with DOI ' .. doi .. '.')
  end
  io.close(file_handle)
end
\end{filecontents*}

% load the main lua code
\directlua{dofile('doidownload.lua')}

% machinery to track downloaded entry keys
\newcommand*{\entrylist}{}
\newcommand*{\entrylistadd}[1]{%
  \xifinlist{\detokenize{#1}}{\entrylist}
    {}
    {\listeadd{\entrylist}{\detokenize{#1}}}}

% {<DOI>}{<entrykey>}
% gets an entry by DOI and assigns the supplied entrykey
\newcommand*{\getdoias}[2]{%
  \xifinlist{\detokenize{#2}}{\entrylist}
    {}
    {\directlua{save_doi_as_key_to('\luaescapestring{#1}',
                                   '\luaescapestring{#2}' ,
                                   '\luaescapestring{\jobname-doidump.bib}')}
     \listeadd{\entrylist}{\detokenize{#2}}}}


% get known keys from .dol file
\IfFileExists{\jobname.dol}{\input{\jobname.dol}}

% write known keys to .dol file to avoid unnecessary queries to crossref API
\makeatletter
\AtEndDocument{%
  \newwrite\dol@out
  \immediate\openout\dol@out\jobname.dol\relax
  \immediate\write\dol@out{%
    \@percentchar\space Do not edit this file\blx@nl
    \@percentchar\space You may, however, safely delete this file if you also delete\blx@nl
    \@percentchar\space\jobname-doidump.bib}%
  \def\do#1{\immediate\write\dol@out{\string\entrylistadd{#1}}}%
  \dolistloop\entrylist
  \immediate\closeout\dol@out}
\makeatother
% if you change a DOI-key pair you should delete the *.dol7
% and *-doidump.bib file to re-enable a clean download

% load the download .bib file
\addbibresource{\jobname-doidump.bib}

% \getdoias can be used in the preamble or the document
\getdoias{10.1002/(SICI)1096-987X(199803)19:4<377::AID-JCC1>3.0.CO;2-P}{sigfridsson}

\begin{document}
\cite{sigfridsson}
\cite{kastenholz}
\getdoias{10.1063/1.2172593}{kastenholz}
\printbibliography
\end{document}

enter image description here

You can see why I think this is a bad idea. I have yet to come across an online service where the downloaded .bib sources did not require manual intervention. See also Software-generated bibliographic entries: common errors and other mistakes to check before use

Here the fact that the url field unnecessarily replicates the DOI sticks out. The month field was incorrectly filled in the two entries. And I forgot to show this, but the ALL CAPS names that one might get (cf. Ross' answer) are also not great.

I suggest you use a reference manager to create your .bib files. Some of them offer a way to obtain an entry from a DOI (certainly JabRef has such a feature, Zotero supports it, Mendeley as well). That has the great advantage that you can actually modify the entry after it has been downloaded (and I firmly believe this is needed in almost all cases) and that the data is more persistent, which allows you to re-use your citations in a different document.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.