1

This answer explains how to create a filter that only has bibliography entries listed by \printbibliography for which field==value is true.

So, to check if an entry belongs to, let's say, Group1, I would define a filter similar to:

\defbibcheck{Group1}{ \iffieldequalstr{groups}{Group1}{}{\skipentry} }

but that obviously can't work because I actually should be checking if Group1 is part of the list groups.

How can that be accomplished?

Here's a M(not)WE:

% !TeX TXS-program:bibliography = txs:///biber
\documentclass{article}

\usepackage[style=authoryear,backend=biber]{biblatex}
\usepackage{filecontents}

\begin{filecontents}{\jobname.bib}
@misc{A01,
  author = {Author, A.},
  year = {2001},
  title = {Alpha},
  groups = {Group1,Group2},
}
@misc{B02,
  author = {Buthor, B.},
  year = {2002},
  title = {Bravo},
  groups = {Group1},
}
@misc{C03,
  author = {Cuthor, C.},
  year = {2003},
  title = {Charlie},
  groups = {Group2},
}
\end{filecontents}

\addbibresource{\jobname.bib}

\begin{document}

\nocite{*}
\defbibcheck{Group1}{ \iffieldequalstr{groups}{Group1}{}{\skipentry} }
\printbibliography[check=Group1]

\end{document}
  • Do you need the arbitrary field "group" there? If you are just trying to screen your bibliography, that could trivially achieved with keywords. – gusbrs Jan 28 at 12:04
  • 2
    I think what he means @gusbrs is that group, as he wants to use it, is not a string field but a list. So he needs a check as to whether the list contains the group. In fact, however, I don't think "group" is a standard field anyway. Shouldn't he be using keyword to filter? I'm afraid I don't have time this morning to fiddle. – Paul Stanley Jan 28 at 12:06
  • @PaulStanley Indeed, my first reading of the question misled me. But I understand it the same way as you do now. And my suggestion is, as yours, to use keywords, except if there are unstated special requirements. – gusbrs Jan 28 at 12:15
3

There are two main reasons why this does not work out of the box as intended.

  1. As mentioned by Paul Stanley in the comments the field groups is not a standard field and therefore not recognised by Biber. That means that the contents of the field groups don't make it to the .bbl file, which in turn means that biblatex can not access its contents.

    You would have to declare the groups field as shown in Add field "tome" to biblatex entries

  2. Secondly, and more seriously, with \iffieldequalstr{<field>}{<string>} you only compare the (entire) contents of the field <field> to the string <string>. That means that \iffieldequalstr{groups}{Group1} yields false when groups is groups = {Group1,Group2},. This is also alluded to in Paul Stanley's comment.

Like gusbrs and Paul Stanley I recommend you look into keywords as that field was intended to filter entries into groups.

\documentclass{article}

\usepackage[style=authoryear,backend=biber]{biblatex}

\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@misc{A01,
  author   = {Author, A.},
  year     = {2001},
  title    = {Alpha},
  keywords = {Group1,Group2},
}
@misc{B02,
  author   = {Buthor, B.},
  year     = {2002},
  title    = {Bravo},
  keywords = {Group1},
}
@misc{C03,
  author   = {Cuthor, C.},
  year     = {2003},
  title    = {Charlie},
  keywords = {Group2},
}
\end{filecontents}

\addbibresource{\jobname.bib}

\begin{document}
\nocite{*}

\printbibliography[keyword=Group1]
\end{document}

If you have already populated hundreds of entries with groups instead of keywords you can use Biber to remap the fields.

\DeclareSourcemap{
  \maps[datatype=bibtex]{
    \map[overwrite]{
      \step[fieldsource=groups, final]
      \step[fieldset=keywords, fieldvalue={,}, append]
      \step[fieldset=keywords, origfieldval, append]
      \step[fieldsource=keywords, match=\regexp{\A,}, replace={}]
    }
  }
}

edit This now uses gusbrs' method from \DeclareSourceMap does not work to avoid a leading comma without an item.


If for some reason you are wedded to the idea of a groups field and don't want to involve keywords at all, here is a crude implementation of a test that loops over a field with comma-separated values and checks if Group1 is contained as list element in the groups field.

\documentclass{article}

\usepackage{filecontents}

% make the groups field known to biblatex
\begin{filecontents*}{groups.dbx}
\DeclareDatamodelFields[type=field,datatype=literal]{groups}
\DeclareDatamodelEntryfields{groups}
\end{filecontents*}
\usepackage[style=authoryear,backend=biber,datamodel=groups]{biblatex}

% traverse the groups field to find a match
\makeatletter
\newtoggle{bastianblx@isgroup}

\newcommand*{\bastianblx@ifmatch}[2]{%
  \ifstrequal{#1}{#2}
    {\toggletrue{bastianblx@isgroup}\listbreak}
    {}}

% switch the order of the arguments for easier \expandafter work
\newcommand*{\bastian@forcsvlist}[2]{%
  \forcsvlist{#2}{#1}}

\defbibcheck{Group1}{%
  \togglefalse{bastianblx@isgroup}%
  % 31 \expandafters for five levels of expansion
  \expandafter\expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\expandafter\expandafter
  \expandafter
  \bastian@forcsvlist
  \expandafter\expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\expandafter\expandafter
  \expandafter
  {\thefield{groups}}{\bastianblx@ifmatch{Group1}}%
  \iftoggle{bastianblx@isgroup}{}{\skipentry}%
}
\makeatother

\begin{filecontents}{\jobname.bib}
@misc{A01,
  author = {Author, A.},
  year   = {2001},
  title  = {Alpha},
  groups = {Group1,Group2},
}
@misc{B02,
  author = {Buthor, B.},
  year   = {2002},
  title  = {Bravo},
  groups = {Group1},
}
@misc{C03,
  author = {Cuthor, C.},
  year   = {2003},
  title  = {Charlie},
  groups = {Group2},
}
\end{filecontents}

\addbibresource{\jobname.bib}

\begin{document}
\nocite{*}

\printbibliography[check=Group1]
\end{document}

All solutions show

Bibliography with two items: <code>A01</code> and <code>B02</code>

  • This is a brilliantly comprehensive answer. The expandafter ghastliness makes my head spin! – Paul Stanley Jan 28 at 13:10
  • That's not an answer, it's a whole "menu"! (+1) You could, though, spread any of the nice techniques to get rid of that leading comma in the sourcemap: tex.stackexchange.com/q/420294/105447. – gusbrs Jan 28 at 13:12
  • @gusbrs Done. The short version I went for (because it avoids code duplication) does not avoid a warning with --trace, though, so I opened github.com/plk/biber/issues/251. – moewe Jan 28 at 14:04
  • @moewe Nice! I had not notice that warning, to be honest. I'll follow the thread there. Thanks. – gusbrs Jan 28 at 14:12
  • @gusbrs I only saw it when I compiled with the --trace option, a normal biber call does not show it. – moewe Jan 28 at 14:13

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.