TransWikia.com

biblatex: continuous reference numbering without duplication

TeX - LaTeX Asked on February 18, 2021

I am using the refsegment feature of biblatex to assemble multiple bibliographies within the same document. I would like to have continuous reference numbering across the refsegments (i.e., if the last new reference of refsegment N is assigned the number i, then the first new reference of refsegment N+1 will be assigned the number i+1). I would also like to avoid duplication of already-cited references in the sub-bibliographies. That is to say, while a given reference may be cited in more than one refsegment, it should be included only in the sub-bibliography for the refsegment in which it first occurs. Here is a simple example:

refsegment #1:
The quick brown fox [1] jumps over the lazy dog [2].
Bibliography:
   [1] Fox reference.
   [2] Dog reference.

refsegment #2:
The lazy dog [2] was busy doing nothing [3].
Bibliography:
   [3] Reference on nothing.

Note that reference #2 was not included in the second bibliography even though it was cited in the second refsegment because it had already been included in the first bibliography.

This post proposed a solution to this problem, namely the onlynew bibliographic check, which suppresses repeated bibliographic items. The proposed solution keeps a running tally of bibliographic items (stored in the control sequence blx@entrycount) and records the next reference number at the start of each refsegment (in the control sequence blx@entrycount@thec@refsegment). Then, if the number assigned to a given bibliographic item (thefield{labelnumber}) is less than (ifnumless{}) the latter quantity, it is skipped in the bibliography (since it has already been referenced). However, upon compilation (TeX Live 2019), all citations are assigned the number zero, the bibliographies are empty, and the following warning is emitted:

LaTeX Warning: Empty bibliography on input line <n>

The below example reproduces the problem. What changes are needed to fix the code in the MWE?


MWE (adapted from linked post):

documentclass{article}
usepackage[defernumbers=true]{biblatex}
usepackage{filecontents}

makeatletter
% Overall entry counter
csnumgdef{blx@entrycount}{0}
AtEveryBibitem{%
  csnumgdef{blx@entrycount}{csuse{blx@entrycount}+1}}

% Continued from this label number
appto{newrefsegment}{%
  csnumgdef{blx@entrycount@thec@refsegment}{csuse{blx@entrycount}+1}}

% Skip entries with label numbers less than the continued number
defbibcheck{onlynew}{%
  ifnumless{thefield{labelnumber}}{csuse{blx@entrycount@thec@refsegment}}
    {skipentry}
    {}}
makeatother

begin{filecontents}{jobname.bib}
@Book{companion,
  author = {Goossens, Michel and Mittelbach, Frank and Samarin, Alexander},
  title = {The LaTeX Companion},
  edition = {1},
  publisher = {Addison-Wesley},
  location = {Reading, Mass.},
  date = {1994}}
@Article{gillies,
  author = {Gillies, Alexander},
  title = {Herder and the Preparation of Goethe's Idea of World Literature},
  journaltitle = {Publications of the English Goethe Society},
  volume = {9},
  date = {1933},
  pages = {46--67}}
@Article{bertram,
  author = {Bertram, Aaron and Wentworth, Richard},
  title = {Gromov invariants for holomorphic maps on Riemann surfaces},
  journaltitle = {J.~Amer. Math. Soc.},
  volume = {9},
  number = {2},
  date = {1996},
  pages = {529--571}}
@Book{poetics,
  author = {Aristotle},
  editor = {Lucas, D. W.},
  title = {Poetics},
  series = {Clarendon Aristotle},
  publisher = {Clarendon Press},
  location = {Oxford},
  date = {1968}}
@Book{rhetoric,
  author = {Aristotle},
  editor = {Cope, Edward Meredith},
  commentator = {Cope, Edward Meredith},
  title = {The Rhetoric of Aristotle with a commentary by the late Edward Meredith Cope},
  volumes = {3},
  publisher = {Cambridge University Press},
  date = {1877}}
end{filecontents}

addbibresource{jobname.bib}

begin{document}

newrefsegment
refsegment therefsegment:
cite{companion,rhetoric}
printbibliography[segment=therefsegment,check=onlynew]

newrefsegment
refsegment therefsegment:
cite{companion,bertram,poetics}
printbibliography[segment=therefsegment,check=onlynew]

newrefsegment
refsegment therefsegment:
cite{companion,bertram,gillies,rhetoric}
printbibliography[segment=therefsegment,check=onlynew]

end{document}

Compilation: pdflatex && biber && pdflatex && pdflatex

Output:

enter image description here

One Answer

The quoted answer is over eight years old and some internal things have changed since then. I can't be absolutely sure, but the main issue seems to be the defernumbers option. With that all labelnumbers are initially set to 0 and non-zero numbers are only assigned once an entry was printed in a bibliography. Unfortunately, the test ifnumless{thefield{labelnumber}}{csuse{blx@entrycount@thec@refsegment}} will always be true if labelnumber is 0, so all entries are skipped in each bibliography, which means that the bibliographies stay empty and thus that blx@entrycount is never increased.

I suggest the following hopefully more stable solution. For each entry it records the first refsegment in which it was cited. The filter onlynew then only needs to check if this refsegment has a number smaller than the current refsegment.

documentclass{article}
usepackage[defernumbers=true]{biblatex}

makeatletter
AtEveryCitekey{%
  ifcsundef{blx@entry@refsegment@thec@refsection @thefield{entrykey}}
    {csnumgdef{blx@entry@refsegment@thec@refsection @thefield{entrykey}}{thec@refsegment}}
    {}}
defbibcheck{onlynew}{%
  ifnumless{0csuse{blx@entry@refsegment@thec@refsection @thefield{entrykey}}}{thec@refsegment}
    {skipentry}
    {}}
makeatother

addbibresource{biblatex-examples.bib}

begin{document}
newrefsegment
refsegment therefsegment:
cite{sigfridsson,worman}
printbibliography[segment=therefsegment,check=onlynew]

newrefsegment
refsegment therefsegment:
cite{sigfridsson,geer,nussbaum}
printbibliography[segment=therefsegment,check=onlynew]

newrefsegment
refsegment therefsegment:
cite{sigfridsson,geer,pines,worman}
printbibliography[segment=therefsegment,check=onlynew]
end{document}

Bibliography with only new entries: 1,2//3,4//5


Here is a solution that also works for nocite. The hook AtEveryEntrykey was added in biblatex 3.15 (see https://github.com/plk/biblatex/issues/934). If you are using an older version of biblatex, please refer to the edit history for a workaround.

documentclass{article}
usepackage[defernumbers=true]{biblatex}

makeatletter
AtEveryEntrykey{%
  ifcsundef{blx@entry@refsegment@thec@refsection @#1}
    {csnumgdef{blx@entry@refsegment@thec@refsection @#1}{thec@refsegment}}
    {}}
  {}{}

defbibcheck{onlynew}{%
  ifnumless{0csuse{blx@entry@refsegment@thec@refsection @thefield{entrykey}}}{thec@refsegment}
    {skipentry}
    {}}
makeatother

addbibresource{biblatex-examples.bib}

begin{document}
newrefsegment
refsegment therefsegment:
cite{sigfridsson,worman}
printbibliography[segment=therefsegment,check=onlynew]

newrefsegment
refsegment therefsegment:
cite{sigfridsson,geer,nussbaum}nocite{knuth:ct:a}
printbibliography[segment=therefsegment,check=onlynew]

newrefsegment
refsegment therefsegment:
cite{sigfridsson,geer,pines,worman}nocite{knuth:ct:a,knuth:ct:b}
printbibliography[segment=therefsegment,check=onlynew]
end{document}

Correct answer by moewe on February 18, 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