4

I'm trying to tweak a biblatex bibliography. One problem is the rendering of entries with eprint fields. Sometimes, I have something like

  eprint         = "hep-ph/0207124",

sometimes its

  eprint         = "0207124",
  primaryClass   = "hep-ph",

but sometimes the class is given in both:

  eprint         = "hep-ph/0207124",
  primaryClass   = "hep-ph",

I'd like to render all consistently in a format like "arXiv:hep-ph/0207124" for example. For this, I tried to customize \DeclareFieldFormat{eprint:arxiv}. My problem is that I can't properly use xstring commands like \IfSubStr or \StrDel in \DeclareFieldFormat. If I try to find primaryClass in eprint, it just doesn't work.

I've traced it down a bit. If #1 is hep-ph/0207124, then

\StrDel{#1}{\thefield{eprintclass}}

doesnt work. It doesn't find the string. I guess I need to make \thefield expand somehow. Even then, directly substituting the string doesn't work either:

\StrDel{#1}{hep-ph}

But it works partially if I use 0 or \string h (but not h) as an argument. I believe it has to do with the catcodes of the arguments. I tried a bunch of \detokenize, \expandafter, \expandarg, but without a systematic approach I can't get it to work.

So how do I use the string manipulation commands properly from within biblatex's field formats?

(Not-quite) minimal (not-quite) working example follows:

\documentclass{article}

\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@article{Witten:2002ei,
      author         = "Witten, Edward",
      title          = "{Quest for unification}",
      pages          = "604-610",
      year           = "2002",
      eprint         = "hep-ph/0207124",
      archivePrefix  = "arXiv",
      primaryClass   = "hep-ph",
      SLACcitation   = "%%CITATION = HEP-PH/0207124;%%",
}
\end{filecontents}

\usepackage[style=numeric,sorting=none]{biblatex}
\addbibresource{\jobname.bib}

\usepackage{xstring}
\makeatletter

\DeclareFieldFormat{eprint:arxiv}{%
  arXiv\addcolon\space%
  \iffieldundef{eprintclass}%
    {#1}%
    {%
    eprint = #1 \par
    class = \thefield{eprintclass} \par
    number = \StrDel{#1}{\thefield{eprintclass}} \par
    removing `0' = \StrDel{#1}{0} \par%
    removing `h' = \StrDel{#1}{h} \par%
    removing `\textbackslash string h' = \StrDel{#1}{\string h} \par%
    }%
}

\makeatother

\begin{document}

\cite{Witten:2002ei}

\printbibliography
\end{document}
1
  • 2
    I would work with DeclareSourceMap and modify all fields global. – Marco Daniel Jan 21 '14 at 19:19
5

The trick was to expand the field, and then convert it to the "other" catcode using a hack found here:

\edef\mytemporary{\thefield{eprintclass}}
\edef\myeprintclass{\expandafter\strip@prefix\meaning\mytemporary}
% then this works as expected:
\StrDel{#1}{\myeprintclass}

The following appends primaryClass + / only if the eprint field doesn't already start with it:

\makeatletter

\newbibmacro{eprint+arxiv}[1]{%
  arXiv\addcolon\space%
  \iffieldundef{eprintclass}%
    {#1}%
    {%
    \edef\mytemporary{\thefield{eprintclass}}%
    \edef\myeprintclass{\expandafter\strip@prefix\meaning\mytemporary}%
    \IfBeginWith{#1}{\myeprintclass/}%
      {#1}%
      {\myeprintclass/#1}%
    }%
}

\DeclareFieldFormat{eprint:arxiv}{%
  \ifhyperref%
    {\href{http://arxiv.org/\abx@arxivpath/#1}{%
      {\usebibmacro{eprint+arxiv}{#1}}%
    }}%
    {\usebibmacro{eprint+arxiv}{#1}}%
}

\makeatother
1
  • 2
    Just for fun, you can avoid the double \edef with \IfBeginWith{#1}{\detokenize\expandafter{\romannumeral-`Q\thefield{eprintclass}}/} instead of \IfBeginWith{#1}{\myeprintclass/}. Of course you must use {\thefield{eprintclass}/#1} as the fourth argument to \IfBeginWith. – egreg Jan 21 '14 at 22:22
5

It's cleaner to do this using biber and \DeclareSourcemap so that you don't have to complicate your style. You need to be using biber 1.9+biblatex 2.9 (both in development folders on SourceForge). Put this in your preamble:

\DeclareSourcemap{
  \maps[datatype=bibtex]{
    \map[overwrite=true]{
       \step[fieldsource=primaryclass, match=\regexp{(.+)}, final]
       \step[fieldsource=eprint, notmatch=\regexp{\A$1/}, final]
       \step[fieldsource=eprint]
       \step[fieldset=primaryclass, fieldvalue=/, append]
       \step[fieldset=primaryclass, origfieldval, append]
       \step[fieldsource=primaryclass, fieldtarget=eprint]
    }
    \map[overwrite=true]{
       \step[fieldset=primaryclass, null]
    }
  }
}
1
  • 2
    I should probably explain why you need biber 1.9/biblatex 2.9 ... this is because the use of previous match buffer like "$1" in other matches was not possible until this version. – PLK Jan 22 '14 at 16:57

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.