6

I would like to print a bibliography which includes all entries with a certain keyword (and possibly some additional entries).

I know that I can filter by keyword when I print the bibliography using

\printbibliography[keyword=<keyword>]

but this will only print entries which I have cited. I could, of course, use

\nocite{*}

to add all entries to the bibliography and then print just those I want.

However, this will make my .bbl file huge as my database is enormous.

Another possibility is to use Biber or another tool to prepare a document-specific .bib file containing only those entries with the keyword. However, this would need to be recreated if additional entries with the keyword are added to my main database files.

Here's an MWE to play with, annotated to indicate the way I'd like it to work ;), and the disadvantages of the way it (almost) works.

The issue of excluding explicitly cited entries is less of an issue for me. The thing I'd really like to work around is adding the entire database contents to the .bbl.

\RequirePackage{filecontents}
\begin{filecontents}{\jobname.bib}
@book{new-stuff,
    author          =   {Watt, Brian},
    title           =   {Happy Times with Penguins},
    publisher       =   {Harvard University Press},
    address         =   {Cambridge, MA},
    year            =   1995,
    pagination      =   {section},
    keywords        =   {happy}}
@book{den-coll,
  author                =   {Till, Jr., Dennis E.},
    booktitle           =   {Penguin Land and Further North: Human Influence},
    title               =   {Penguin Land and Further North: Human Influence},
    publisher           =   {Oxford University Press},
    year                =   2008,
    address             =   {Oxford and New York},
    keywords            =   {penguin, human}}
@book{old-stuff,
  author                =   {Harvey, Jr., Dennis E.},
    booktitle           =   {Penguin Land and Further North: Human Influence},
    title               =   {Penguin Land and Further North: Human Influence},
    publisher           =   {Someone \& Daughters},
    year                =   1567,
    address             =   {Oxford},
    bookpagination      =   {paragraph},
    keywords            =   {penguin}}
\end{filecontents}
\documentclass{article}
\usepackage[defernumbers=true]{biblatex}
\bibliography{\jobname}
\begin{document}

\cite{old-stuff}

% what I would like to work
% \nocite[keyword=happy]
% \printbibliography

% what does work - except that \cite{old-stuff} is ignored and, more importantly, den-coll is added to the .bbl
\nocite{*}
\printbibliography[keyword=happy]

\end{document}
  • As far as I know, the keyword filtering can only work if the entry is actually in the .bbl file, otherwise biblatex has no way to know about the presence or absence of a keyword. Using Biber, we can simply ignore all entries without (or with) a certain keyword (see entrynull), of course previous \cite commands cannot help us here. – moewe Aug 5 '15 at 17:33
  • What about using the strategy used in this question tex.stackexchange.com/q/244620/16895? where you use a first round of computation with \cite{*} and then a second round where you include a no cite for the entries with the appropriate keywords. – Guido Aug 5 '15 at 17:40
  • @Guido The first round is going to take forever. \cite{*} will produce an enormous .bbl, just as \nocite{*} would. (It would let me then include additional entries, so it would have that advantage. But the main downside would be the same.) – cfr Aug 5 '15 at 20:55
  • @moewe I was afraid of that. And, actually, even the feature requested wouldn't help. I need to extract entries from .bib files and I don't want to end up with a .bbl with 3,000+ entries just so I can filter out a couple of handfuls. I would think that keyword filtering would be very useful at the document level but perhaps I'm wrong and there's just no real demand for it. – cfr Aug 5 '15 at 21:02
6

Update: This is now possible with biber 2.14/biblatex 3.14, both in their respective development folders on github [1][2]:

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.bib}
@book{new-stuff,
    author          =   {Watt, Brian},
    title           =   {Happy Times with Penguins},
    publisher       =   {Harvard University Press},
    address         =   {Cambridge, MA},
    year            =   1995,
    pagination      =   {section},
    keywords        =   {happy}}
@book{den-coll,
  author                =   {Till, Jr., Dennis E.},
    booktitle           =   {Penguin Land and Further North: Human Influence},
    title               =   {Penguin Land and Further North: Human Influence},
    publisher           =   {Oxford University Press},
    year                =   2008,
    address             =   {Oxford and New York},
    keywords            =   {penguin, human}}
@book{old-stuff,
  author                =   {Harvey, Jr., Dennis E.},
    booktitle           =   {Penguin Land and Further North: Human Influence},
    title               =   {Penguin Land and Further North: Human Influence},
    publisher           =   {Someone \& Daughters},
    year                =   1567,
    address             =   {Oxford},
    bookpagination      =   {paragraph},
    keywords            =   {penguin}}
\end{filecontents*}

\usepackage[defernumbers=true]{biblatex}
\addbibresource{\jobname.bib}
\DeclareSourcemap{
  \maps[datatype=bibtex]{
    \map{
      \step[nocited, final]
      \step[fieldsource=keywords, notmatch=happy, final]
      \step[entrynull]
    }
  }
}

\begin{document}

\cite{old-stuff}

\nocite{*}
\printbibliography

\end{document}

This removes entries during parsing the data sources which are \nocited or which don't have the keyword.

enter image description here

  • This used to be impossible but biber for quite some time now has had access to the refsection information on entry key origins when parsing the data sources which makes some things now possible. – PLK Sep 11 at 13:46
  • Excellent! Thank you so much. (Not tested yet - currently struggling with TL2019 updating.) – cfr Sep 29 at 18:40
3

This is an old question, and it doesn't look like there is a really satisfactory answer. But here's a solution that involves a perl script just for fun.

Remember to run it with pdflatex --enable-write18.

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{allentries.bib}
@book{new-stuff,
    author          =   {Watt, Brian},
    title           =   {Happy Times with Penguins},
    publisher       =   {Harvard University Press},
    address         =   {Cambridge, MA},
    year            =   1995,
    pagination      =   {section},
    keywords        =   {happy}}
@book{den-coll,
  author                =   {Till, Jr., Dennis E.},
    booktitle           =   {Penguin Land and Further North: Human Influence},
    title               =   {Penguin Land and Further North: Human Influence},
    publisher           =   {Oxford University Press},
    year                =   2008,
    address             =   {Oxford and New York},
    keywords            =   {penguin, human}}
@book{old-stuff,
  author                =   {Harvey, Jr., Dennis E.},
    booktitle           =   {Penguin Land and Further North: Human Influence},
    title               =   {Penguin Land and Further North: Human Influence},
    publisher           =   {Someone \& Daughters},
    year                =   1567,
    address             =   {Oxford},
    bookpagination      =   {paragraph},
    keywords            =   {penguin}}
\end{filecontents*}
\begin{filecontents*}{citekeyword.pl}
use strict;
use warnings;
use Text::BibTeX;
my $keyword = "happy"; # set keyword here
my $bibfile = Text::BibTeX::File->new("allentries.bib");
my $keywordcitefile = "keywordcites.tex";
open(my $fh, '>', $keywordcitefile) or
    die "Could not open file '$keywordcitefile' $!";
my $keywords;
my $entry;
while ($entry = Text::BibTeX::Entry->new($bibfile)) {
    next unless $entry->parse_ok;
    if ($entry->get("keywords")) {
        $keywords = "," . $entry->get("keywords") . ",";
        if ($keywords =~ /,$keyword,/) {
            print $fh "\\nocite{" . $entry->key . "}\n";
        }
    }
}
close $fh;
\end{filecontents*}
\immediate\write18{/usr/bin/perl citekeyword.pl}
\usepackage[defernumbers=true]{biblatex}
\addbibresource{allentries.bib}
\pagestyle{empty}
\begin{document}
\input{keywordcites.tex}
\cite{old-stuff}
\printbibliography
\end{document}

enter image description here

  • Very nice! I hope you don't mind that I won't accept your answer, as it really doesn't answer the question. As you mentioned, there probably isn't a satisfactory answer. But definitely more than worth an up-vote :-). – cfr Sep 3 '17 at 13:45
  • haha no worries. It is technically within the document code, just not what you hoped for. ;) – David Purton Sep 3 '17 at 14:26
  • Yes, it is a bit unfair. It is just that if it stays open, well, who knows whether it might get the perfect answer in a couple of decades or so? Some descendant of Biber/Biblatex, perhaps .... Of course, the world may end before then, but at least I can dream :-). – cfr Sep 3 '17 at 20:09
  • 1
    Not even 2 decades - only 2 years! I thought you might want to see the answer from PLK above. – cfr Sep 29 at 18:41

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.