3

A previous question here asks whether it is possible for Biblatex to print an entry's ISBN only if it doesn't already contain a DOI. The accepted answer by Andrew Swann is to use Biblatex's source remapping features to check whether the doi field is non-null, and if so, to clear the isbn field so that it is not printed.

The problem with this solution is that it does not work for cross-referenced entries. For example, say you have a @proceedings entry with an isbn field, and an @inproceedings entry with a doi field as well as a crossref field that references the @proceedings entry. In this case, when the @inproceedings entry gets printed in the list of references, both the DOI and ISBN are displayed.

Here is a minimal example and the output:

\documentclass{article}
\usepackage[backend=biber]{biblatex}
\addbibresource{\jobname.bib}
\DeclareSourcemap{
  \maps[datatype=bibtex]{
     \map{
        \step[fieldsource=doi,final]
        \step[fieldset=isbn,null]
        }
      }
}

\begin{filecontents}{\jobname.bib}
@proceedings{book1,
  editor = {Adam Author},
  title = {Book One},
  year = 2020,
  doi = {10.1000/1010},
  note = {DOI only},
}

@proceedings{book2,
  editor = {Betty Bookwriter},
  title = {Book Two},
  year = 2020,
  doi = {10.1000/2020},
  isbn = {123-456-789},
  note = {DOI and ISBN; ISBN should not be displayed},
}

@proceedings{book3,
  editor = {Edward Editor},
  title = {Book Three},
  year = 2020,
  isbn = {123-456-789},
  note = {ISBN only},
}

@inproceedings{article4,
  author =   {Sally Scribe},
  title =    {Article Four},
  doi =      {10:1000/4040},
  crossref = {book3},
  note = {DOI from article, ISBN from crossref should not be displayed},
}

@inproceedings{article5,
  author =   {Walter Writer},
  title =    {Article Five},
  crossref = {book3},
  note = {ISBN from crossref should be displayed},
}
\end{filecontents}

\begin{document}
\nocite{book1,book2,book3,article4,article5}
\printbibliography
\end{document}

Output of the above LaTeX document, showing that article4 is incorrectly printed with both an ISBN and DOI

How can Andrew's answer be adapted so that it accounts for isbn and doi fields in cross-referenced entries? Or failing this, is there some other solution (short of manually editing the bibliography entries) that will achieve this?

1 Answer 1

4

Sourcemaps are executed fairly early in the .bib parsing process way before field aliasing and data inheritance has been applied. This means that your sourcemap simply doesn't know whether an entry will inherit a certain field or not.

It is probably best to suppress the field only on the biblatex once all data is available. The conceptually nicest way probably goes through \AtDataInput, but it needs a new helper macro.

\documentclass{article}
\usepackage[backend=biber]{biblatex}

\makeatletter
\newcommand*{\ClearFieldAtDataInput}[1]{%
  \csxappto\blx@bbl@data{%
    \undef\expandafter\noexpand\csname abx@field@#1\endcsname}}
\makeatother

\AtDataInput{%
  \iffieldundef{doi}
    {}
    {\ClearFieldAtDataInput{isbn}}}

\begin{filecontents}{\jobname.bib}
@proceedings{book1,
  editor = {Adam Author},
  title  = {Book One},
  year   = 2020,
  doi    = {10.1000/1010},
  note   = {DOI only},
}
@proceedings{book2,
  editor = {Betty Bookwriter},
  title  = {Book Two},
  year   = 2020,
  doi    = {10.1000/2020},
  isbn   = {123-456-789},
  note   = {DOI and ISBN; ISBN should not be displayed},
}
@proceedings{book3,
  editor = {Edward Editor},
  title  = {Book Three},
  year   = 2020,
  isbn   = {123-456-789},
  note   = {ISBN only},
}
@inproceedings{article4,
  author   = {Sally Scribe},
  title    = {Article Four},
  doi      = {10:1000/4040},
  crossref = {book3},
  note     = {DOI from article, ISBN from crossref should not be displayed},
}
@inproceedings{article5,
  author   = {Walter Writer},
  title    = {Article Five},
  crossref = {book3},
  note     = {ISBN from crossref should be displayed},
}
\end{filecontents}
\addbibresource{\jobname.bib}

\begin{document}
\nocite{book1,book2,book3,article4,article5}
\printbibliography
\end{document}

[1] Adam Author, ed. Book One. DOI only. 2020. doi: 10.1000/1010.//[2] Betty Bookwriter, ed. Book Two. DOI and ISBN; ISBN should not be displayed. 2020. doi: 10.1000/2020.//[3] Edward Editor, ed. Book Three. ISBN only. 2020. isbn: 123-456-789.//[4] Sally Scribe. “Article Four”. In: Book Three. Ed. by Edward Editor. DOI from article, ISBN from crossref should not be displayed. 2020. doi: 10:1000/4040.//[5] Walter Writer. “Article Five”. In: Book Three. Ed. by Edward Editor. ISBN from crossref should be displayed. 2020. isbn: 123-456-789.


Alternatively, you can use the standard \AtEveryBibitem/\AtEveryCitekey hooks

\documentclass{article}
\usepackage[backend=biber]{biblatex}

\newcommand*{\clearisbn}{%
  \iffieldundef{doi}
    {}
    {\clearfield{isbn}}}

\AtEveryBibitem{\clearisbn}
\AtEveryCitekey{\clearisbn}

\begin{filecontents}{\jobname.bib}
@proceedings{book1,
  editor = {Adam Author},
  title  = {Book One},
  year   = 2020,
  doi    = {10.1000/1010},
  note   = {DOI only},
}
@proceedings{book2,
  editor = {Betty Bookwriter},
  title  = {Book Two},
  year   = 2020,
  doi    = {10.1000/2020},
  isbn   = {123-456-789},
  note   = {DOI and ISBN; ISBN should not be displayed},
}
@proceedings{book3,
  editor = {Edward Editor},
  title  = {Book Three},
  year   = 2020,
  isbn   = {123-456-789},
  note   = {ISBN only},
}
@inproceedings{article4,
  author   = {Sally Scribe},
  title    = {Article Four},
  doi      = {10:1000/4040},
  crossref = {book3},
  note     = {DOI from article, ISBN from crossref should not be displayed},
}
@inproceedings{article5,
  author   = {Walter Writer},
  title    = {Article Five},
  crossref = {book3},
  note     = {ISBN from crossref should be displayed},
}
\end{filecontents}
\addbibresource{\jobname.bib}

\begin{document}
\nocite{book1,book2,book3,article4,article5}
\printbibliography
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .