4

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@\the\c@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@\the\c@refsegment}{\csuse{blx@entrycount}+1}}

% Skip entries with label numbers less than the continued number
\defbibcheck{onlynew}{%
  \ifnumless{\thefield{labelnumber}}{\csuse{blx@entrycount@\the\c@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

4
  • 1
    Basically this bib system means that if in segment N there is a cite, the reader has to search for the bib entry in N reference sections starting probably on N different pages - sounds like a very effective way to discourage a reader to ever check a source. Commented Nov 25, 2019 at 7:48
  • @UlrikeFischer: I agree. This is the requirement I face, however.
    – user001
    Commented Nov 25, 2019 at 7:52
  • Well my point of view is that if someone requires such nonsense they should pay for the implementation of their whims instead of asking the volonteers to do it for free. Commented Nov 25, 2019 at 8:17
  • @UlrikeFischer: I think you misunderstand. The asker and requirer are separate; for all the requirer cares, this can be done in Microsoft Word.
    – user001
    Commented Nov 25, 2019 at 9:10

1 Answer 1

3

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@\the\c@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@\the\c@refsection @\thefield{entrykey}}
    {\csnumgdef{blx@entry@refsegment@\the\c@refsection @\thefield{entrykey}}{\the\c@refsegment}}
    {}}
\defbibcheck{onlynew}{%
  \ifnumless{0\csuse{blx@entry@refsegment@\the\c@refsection @\thefield{entrykey}}}{\the\c@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@\the\c@refsection @#1}
    {\csnumgdef{blx@entry@refsegment@\the\c@refsection @#1}{\the\c@refsegment}}
    {}}
  {}{}

\defbibcheck{onlynew}{%
  \ifnumless{0\csuse{blx@entry@refsegment@\the\c@refsection @\thefield{entrykey}}}{\the\c@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}
14
  • Thanks moewe, that works well. I'm wondering if you could clarify a few minor points: (1) Is blx@entry@refsegment@\the\c@refsection @\thefield{entrykey} a single control sequence (with a space in the middle)? (2) Is entrykey the .bib file entry key (e.g., sigfridsson)? Finally, (3) does contatenation of 0 and \csuse{blx@entry@refsegment@\the\c@refsection @\thefield{entrykey} make the first argument of \ifnumless zero if the control sequence specified by \csuse{} is undefined?
    – user001
    Commented Nov 20, 2019 at 16:50
  • 2
    @user001 (1) In ..cs.. macros blx@entry@refsegment@\the\c@refsection @\thefield{entrykey} gets expanded before forming the control sequence name, so this becomes for example blx@entry@refsegment@0@sigfridsson for sigfridsson in refsection 0, the space after \c@refsection is swallowed by the usual TeX rules (for more on ...cs... macros see also Phelype's explanations to your recent question tex.stackexchange.com/a/517205/35864). (2) Yes, within biblatex we can access the entry key with \thefield{entrykey}. (3) Yes.
    – moewe
    Commented Nov 20, 2019 at 19:13
  • Many thanks for clarifying.
    – user001
    Commented Nov 20, 2019 at 19:38
  • 1
    @user001 See the updated answer, please.
    – moewe
    Commented Nov 21, 2019 at 18:49
  • 1
    github.com/plk/biblatex/issues/934
    – moewe
    Commented Nov 21, 2019 at 18:49

You must log in to answer this question.

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