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

  • 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. – Ulrike Fischer Nov 25 '19 at 7:48
  • @UlrikeFischer: I agree. This is the requirement I face, however. – user001 Nov 25 '19 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. – Ulrike Fischer Nov 25 '19 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 Nov 25 '19 at 9:10
2

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. Since there is no \AtEveryCitekey-equivalent for \nocite we have to hook into internal commands.

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

\makeatletter
\def\blx@citation@entry#1#2{%
  \blx@bibreq{#1}%
  \ifinlist{#1}\blx@cites
    {}
    {\listgadd{\blx@cites}{#1}}%
  \blx@auxwrite\@mainaux{}{\string\abx@aux@cite{#1}}%
  \ifinlistcs{#1}{blx@segm@\the\c@refsection @\the\c@refsegment}
    {}
    {\listcsgadd{blx@segm@\the\c@refsection @\the\c@refsegment}{#1}}%
  \blx@auxwrite\@mainaux{}{\string\abx@aux@segm{\the\c@refsection}%
                                               {\the\c@refsegment}%
                                               {\detokenize{#1}}}%
  \ifcsundef{blx@entry@refsegment@\the\c@refsection @#1}
    {\csnumgdef{blx@entry@refsegment@\the\c@refsection @#1}{\the\c@refsegment}}
    {}%
  \blx@ifdata{#1}
    {}
    {\ifcsdef{blx@miss@\the\c@refsection}
       {\ifinlistcs{#1}{blx@miss@\the\c@refsection}
          {}
          {\blx@logreq@active{#2{#1}}}}
       {\blx@logreq@active{#2{#1}}}}}

\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}
| improve this answer | |
  • 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 Nov 20 '19 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 Nov 20 '19 at 19:13
  • Many thanks for clarifying. – user001 Nov 20 '19 at 19:38
  • 1
    @user001 See the updated answer, please. – moewe Nov 21 '19 at 18:49
  • 1
    github.com/plk/biblatex/issues/934 – moewe Nov 21 '19 at 18:49

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.