TransWikia.com

Biblatex equivalent to labeled multibib with working hyperref

TeX - LaTeX Asked by foens on August 27, 2021

I have a document using a labeled version of multibib, i.e. usepackage[labeled]{multibib}. However, hyperref does not work on the cites and according to “Why does hyperlink point to a wrong page when option “labeled” for multibib is activated?“, it seems one should use biblatex.

How can I achieve the same result as usepackage[labeled]{multibib} using biblatex and have hyperref work correctly?

To be concrete, how can the minimal example document below be translated to biblatex?

documentclass{article}
usepackage[labeled]{multibib}
usepackage{hyperref}

begin{filecontents}{A.bbl}
    begin{thebibliography}{1}
        bibitem{slam2001}
        Thomas Ball and Sriram~K. Rajamani.
        newblock Automatically validating temporal safety properties of interfaces.
        newblock In {em Proceedings of the 8th International SPIN Workshop on Model
          Checking of Software}, 2001.
    end{thebibliography}
end{filecontents}

begin{filecontents}{B.bbl}
    begin{thebibliography}{1}
        bibitem{blast2007}
        Dirk Beyer, Thomas~A. Henzinger, Ranjit Jhala, and Rupak Majumdar.
        newblock The software model checker blast: Applications to software
          engineering.
        newblock {em International Journal on Software Tools for Technology
          Transfer}, 2007.
    end{thebibliography}
end{filecontents}

newcites{A,B}{Primary,Secondary}

begin{document}
CiteA~citeA{slam2001}, CiteB~citeB{blast2007}

bibliographyA{refs}
bibliographyB{refs}
end{document}

The example produces the following using pdflatex where the hyperref does not work correctly on cites:

Output from above tex document

One Answer

You could try the following.

We will presume we have two .bib files: jobname-1.bib and jobname-2.bib, here created via filecontents*

begin{filecontents*}{jobname-1.bib}
@inproceedings{slam2001,
  author    = {Thomas Ball and Sriram K. Rajamani},
  title     = {Automatically Validating Temporal Safety Properties of Interfaces},
  booktitle = {Proceedings of the 8th International SPIN Workshop on Model Checking of Software},
  editor    = {Matthew Dwyer},
  date      = {2001},
}
end{filecontents*}
begin{filecontents*}{jobname-2.bib}
@article{blast2007,
  author    = {Dirk Beyer and Thomas A. Henzinger and Ranjit Jhala and Rupak Majumdar},
  title     = {The software model checker {BLAST}},
  subtitle  = {Applications to software engineering},
  journal   = {International Journal on Software Tools for Technology Transfer},
  date      = {2007},
  volume    = {9},
}
end{filecontents*}


addbibresource{jobname-1.bib}
addbibresource{jobname-2.bib}

These two files will be added to different keywords with Biber's sourcemapping

DeclareSourcemap{
  maps[datatype=bibtex]{
    map{
      perdatasource{jobname-1.bib}
      step[fieldset=keywords, fieldvalue={, primary}, append]
    }
    map{
      perdatasource{jobname-2.bib}
      step[fieldset=keywords, fieldvalue={, secondary}, append]
    }
  }
}

jobname-1.bib gets the keyword primary, jobname-2.bib gets secondary. (I chose primary and secondary here, but you can pick anything you like. Just make sure that these keywords are not used for anything else in your .bib file or in your bibliography setup.) Note that the names of the .bib files are 'hard-coded' in perdatasource. If you have different files names, you need to adapt the code accordingly.

If you insist on continuous numbering (i.e. do not want the second bibliography to start at [B1]) we'll need to put an end to biblatex's auto-detection of resetnumbers in case labelprefix is used:

makeatletter
providerobustcmd*{blx@kv@defkey}{define@key}

blx@kv@defkey{blx@bib1}{noresetnumbersforlabelprefix}[true]{%
  ifstrequal{#1}{true}
    {letblx@saved@refcontext@labelprefixblx@refcontext@labelprefix
     letblx@saved@refcontext@labelprefixblx@refcontext@labelprefix@real
     letblx@refcontext@labelprefix@empty
     letblx@refcontext@labelprefix@real@empty}
    {}}

blx@kv@defkey{blx@bib2}{noresetnumbersforlabelprefix}[true]{%
  ifstrequal{#1}{true}
    {letblx@refcontext@labelprefixblx@saved@refcontext@labelprefix
     letblx@refcontext@labelprefix@realblx@saved@refcontext@labelprefix}
    {}}
makeatother

All the entries can be cited via cite (so the keyword does not matter, there is not citeA or citeB).

The bibliography is printed with

newrefcontext[labelprefix=A]
printbibliography[keyword=primary, noresetnumbersforlabelprefix, title=Primary]
newrefcontext[labelprefix=B]
printbibliography[keyword=secondary, noresetnumbersforlabelprefix, title=Secondary]

That is the first bibliography only contains entries with the keyword primary (effectively that is entries from joabname-1.bib), while the second contains secondary entries (jobname-2.bib). I have added prefixes to the labels via the labelprefix option of newrefcontext (that comes closer to your example). The heading/title is controlled by the title option.

MWE

documentclass{article}
usepackage[style=numeric, defernumbers=true, backend=biber, maxnames=999]{biblatex}
usepackage{hyperref}

DeclareSourcemap{
  maps[datatype=bibtex]{
    map{
      perdatasource{jobname-1.bib}
      step[fieldset=keywords, fieldvalue={, primary}, append]
    }
    map{
      perdatasource{jobname-2.bib}
      step[fieldset=keywords, fieldvalue={, secondary}, append]
    }
  }
}

makeatletter
providerobustcmd*{blx@kv@defkey}{define@key}

blx@kv@defkey{blx@bib1}{noresetnumbersforlabelprefix}[true]{%
  ifstrequal{#1}{true}
    {letblx@saved@refcontext@labelprefixblx@refcontext@labelprefix
     letblx@saved@refcontext@labelprefixblx@refcontext@labelprefix@real
     letblx@refcontext@labelprefix@empty
     letblx@refcontext@labelprefix@real@empty}
    {}}

blx@kv@defkey{blx@bib2}{noresetnumbersforlabelprefix}[true]{%
  ifstrequal{#1}{true}
    {letblx@refcontext@labelprefixblx@saved@refcontext@labelprefix
     letblx@refcontext@labelprefix@realblx@saved@refcontext@labelprefix}
    {}}
makeatother

begin{filecontents*}{jobname-1.bib}
@inproceedings{slam2001,
  author    = {Thomas Ball and Sriram K. Rajamani},
  title     = {Automatically Validating Temporal Safety Properties of Interfaces},
  booktitle = {Proceedings of the 8th International SPIN Workshop on Model Checking of Software},
  editor    = {Matthew Dwyer},
  date      = {2001},
}
@article{blast2008,
  author    = {Dirk Beyer and Thomas A. Henzinger and Ranjit Jhala and Rupak Majumdar},
  title     = {BLAST II},
  journal   = {International Journal on Software Tools for Technology Transfer},
  date      = {2008},
  volume    = {18},
}
end{filecontents*}
begin{filecontents*}{jobname-2.bib}
@article{blast2007,
  author    = {Dirk Beyer and Thomas A. Henzinger and Ranjit Jhala and Rupak Majumdar},
  title     = {The software model checker {BLAST}},
  subtitle  = {Applications to software engineering},
  journal   = {International Journal on Software Tools for Technology Transfer},
  date      = {2007},
  volume    = {9},
}
@inproceedings{slam2002,
  author    = {Thomas Ball and Sriram K. Rajamani},
  title     = {Interfaces are Cool!},
  booktitle = {Proceedings of the 8th International SPIN Workshop on Model Checking of Software},
  date      = {2002},
}
end{filecontents*}
addbibresource{jobname-1.bib}
addbibresource{jobname-2.bib}

begin{document}
CiteA~cite{slam2001,slam2002}, CiteB~cite{blast2007,blast2008}

newrefcontext[labelprefix=A]
printbibliography[keyword=primary, noresetnumbersforlabelprefix, title=Primary]
newrefcontext[labelprefix=B]
printbibliography[keyword=secondary, noresetnumbersforlabelprefix, title=Secondary]
end{document}

CiteA [A1, B3], CiteB [B4, A2]

Hyperlinking seemed to work rather well here.

edit The answer was updated to work with more recent versions of biblatex (tested with v3.14, but it should work from v3.12 onward). If you are using an ancient version of biblatex (v3.3 or below), please refer to the edit history.

Correct answer by moewe on August 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP