3

I am trying to add a field to biblatex entries in the texfile. I am currently not able to apply a rule to one entry then apply it other rules to other entries.

I defined a command to add a field. Something is wrong with it but I don't know what it is:

\newcommand{\addnotetoentry}[2]{%
  \DeclareSourcemap{%
  \maps[datatype=bibtex]{%
    \map[overwrite]{%
      \step[fieldsource=entrykey,match=\regexp{^#1$},final]%
      \step[fieldset=note,fieldvalue={#2}]%
    }%
  }%
}%
}

Which is used like this:

\addnotetoentry{a}{one note --- hello my friend}
\addnotetoentry{b}{another note}

MWE:

\documentclass[12pt,letterpaper]{article}
\usepackage[backend=biber,style=alphabetic-verb,doi=false,eprint=false]{biblatex}
\usepackage{filecontents}

\begin{filecontents}{jobname.bib}
@ARTICLE{a,
   author = {Doe, J.},
   title = {The Title},
   journal = {The Journal},
}
@ARTICLE{b,
   author = {Smith, J.},
   title = {The New Title},
   journal = {The Same Journal},
}
\end{filecontents}
\addbibresource{jobname.bib}

\newcommand{\addnotetoentry}[2]{%
  \DeclareSourcemap{%
  \maps[datatype=bibtex]{%
    \map[overwrite]{%
      \step[fieldsource=entrykey,match=\regexp{^#1$},final]%
      \step[fieldset=note,fieldvalue={#2}]%
    }%
  }%
}%
}
\addnotetoentry{a}{one note}
\addnotetoentry{b}{another note}
\AtEveryBibitem{\printfield{note}\clearfield{note}\item}

\begin{document}

\nocite{*}
\printbibliography
\end{document}

I get in the ouput's references only one note (the last one that I defined):

buggy output

  • I currently cannot find the reference in the documentation, but I am pretty sure one can only use one \DeclareSourcemap per document (only the last one will be executed), one can use an unlimited (I think) number of \maps in a \DeclareSourcemap though. – moewe Apr 10 '14 at 15:02
  • What exactly do you want to do? It is probably not the best idea to change bibliography data on the fly in a document. If you have to change anything, change the .bib file. – moewe Apr 10 '14 at 15:11
  • I don't want to modify my bib file to add notes. Since the bib file is dynamically generated remotely. – pastjean Apr 10 '14 at 15:25
  • I feared you'd have a good reason to do that... I think we will have to look for a different solution. \DeclareSourcemap in this form does not look like your best bet... – moewe Apr 10 '14 at 15:29
  • declaring multiple map into one source map works (just tried), so i'm searching for a way to add maps using a command (to make it easier) , I'll look into the implementation of DeclareSourcemap – pastjean Apr 10 '14 at 15:32
3

The problem with Biber's \DeclareSourcemap is that it may only be used once in a document (only the last instance will be executed, all the other calls will be ignored)*, as such it is quite hard to implement a macro using \DeclareSourcemap.

If you just want to add a comment to some bibliography entries, we can go down a different route.

\newcommand*{\writecomment}[2]{\csdef{localcomment#1}{#2}}

We define \writecomment to define a macro localcomment<entrykey> (<entrykey> as given in #1) that takes the value #2.

That macro localcomment<entrykey> can then be used as \csuse{localcomment<entrykey>}, like so

Before every element:

\AtEveryBibitem{\csuse{localcomment\thefield{entrykey}}\item}

Or after every element:

\renewbibmacro*{finentry}{%
  \finentry
  \ifcsdef{localcomment\thefield{entrykey}}
    {\\\csuse{localcomment\thefield{entrykey}}}
    {}%
}

\csuse will not do anything if its argument is not a valid command sequence; that means, if the macro was not created via \writecomment this will result in no output at all.

Another plus side of this solution is that we do not have to fiddle with the note field and do not override existing notes.

Usage of \writecomment is straightforward: \writecomment{<entrykey>}{<note>}

\writecomment{a}{first comment}
\writecomment{b}{second comment}

MWE

\documentclass{article}
\usepackage[backend=biber,style=alphabetic-verb,doi=false,eprint=false]{biblatex}
\begin{filecontents}{jobname.bib}
@ARTICLE{a,
   author = {Doe, J.},
   title = {The Title},
   journal = {The Journal},
}
@ARTICLE{b,
   author = {Smith, J.},
   title = {The New Title},
   journal = {The Same Journal},
}
@ARTICLE{c,
   author = {Miller, J.},
   title = {The New Title},
   journal = {Won't Get A Comment},
}
\end{filecontents}
\addbibresource{jobname.bib}

\newcommand*{\writecomment}[2]{\csdef{localcomment#1}{#2}}
\AtEveryBibitem{\csuse{localcomment\thefield{entrykey}}\item}

\writecomment{a}{first comment}
\writecomment{b}{second comment}

\begin{document}
  \nocite{*}
  \printbibliography
\end{document}

enter image description here

* I cannot find any piece of documentation that backs this claim up, but I'm quite confident it is correct.

| improve this answer | |
  • Thank you very much, this is exactly what I was trying to do, but in a simpler way! – pastjean Apr 10 '14 at 15:44
  • @pastjean I noticed you have included your use case in my answer, I have slightly modified the solution to use \renewbibmacro*{finentry}{\finentry \ifcsdef{localcomment\thefield{entrykey}} {\\\csuse{localcomment\thefield{entrykey}}}{}} instead. That seems more apt than redefining the \finentrypunct, plus it will check if there is any comment and if that is not the case, no line break will be inserted. – moewe Apr 11 '14 at 16:55
2

So apparently you cannot add multiple \DeclareSourcemap to a latex file since only the last one it taken into account.


One Solution can be to declare only one source map and modify the entries manually

\DeclareSourcemap{
  \maps[datatype=bibtex]{
    \map[overwrite]{
      \step[fieldsource=entrykey,match=\regexp{^a$},final]
      \step[fieldset=note,fieldvalue={one note}]
    }
    \map[overwrite]{
      \step[fieldsource=entrykey,match=\regexp{^b$},final]
      \step[fieldset=note,fieldvalue={another note}]
    }
  }
}
| improve this answer | |

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.