18

The first given name of an author or editor in my bibliography should be written out, but all further first names should be abbreviated (initials with a period -- and space if there are multiple first names/initials, see below). I am using style=authoryear with BibLaTeX (v. 2.7) and Biber (v. 1.7).

My bibliography looks like this:

Doe, John Arthur Kyle (2013). The secret life of John Doe.

It should look like this:

Doe, John A. K. (2013). The secret life of John Doe.

Minimal example:

example.tex

\documentclass{scrartcl}

\usepackage[ngerman]{babel}
\usepackage[babel,german=quotes]{csquotes}
\usepackage[backend=biber,style=authoryear]{biblatex}
\bibliography{bibliography}

\begin{document}

\cite[123]{Doe}
\printbibliography

\end{document}

bibliography.bib

@book{Doe,
    title = {The secret life of John Doe},
    author = {Doe, John Arthur Kyle},
    year = {2013}
}

(Worked with said versions of BibLaTeX and Biber, Texmaker (v. 4.0.3) and MiKTeX (v. 2.9.4813).)

I could not find a solution in biblatex.def and firstinits=true abbreviates all first names, including the first one.

  • Check out section 4.4.2 of the biblatex manual to get started. However, the fact that biblatex does not seem to distinguish between the first name and (even multiple) middle names suggests this might not be that easy to achieve .... – Jonathan Jul 30 '13 at 22:02
  • \DeclareNameFormat seems to be the right way. Even if I ignore middle names, I cannot find a way to 'tokenize' the list of first (and middle) names. Next step would be assign style #3 (first names written out) to the first token (\ifnumequal{1}) and style #4 (first names as initials) to the rest (\ifnumgreater{1} or some kind of 'else' resulting from \DeclareNameFormat syntax). – G. H. Jul 31 '13 at 12:31
13

As biblatex does not distinguish multiple first names, we need to split this list ourselves:

\makeatletter
\def\@empty{}
\def\first#1{\expandafter\@first#1 \@nil}
\def\@first#1 #2\@nil{#1\addspace%
  \if\relax\detokenize{#2}\relax\else\@initials#2\@nil\fi}
\def\initials#1{\expandafter\@initials#1 \@nil}
\def\@initials#1 #2\@nil{%
  \initial{#1}%
  \def\NextName{#2}%
  \ifx\@empty\NextName\relax%
  \else\@initials#2\@nil\fi}
\def\initial#1{\expandafter\@initial#1\@nil}
\def\@initial#1#2\@nil{#1.\addspace}
\makeatother

Now calling \first{John Arthur Kyle} yields "John A. K.".

The trick used is that the macro \first passes its argument to \@first which in turn delimits its arguments by spaces, i.e. #1 is "John" and #2 is "Arthur Kyle". This gets sent to \@initials which goes through the list of names (in case there are more or less than two) and calls \initial with each name. \initial in turn calls \@initial which throws away all but the first letter and adds a dot and a space.

Now we can use this in \DeclareNameFormat:

\def\bibnamedelima{ }%
\def\bibnamedelimb{ }%
\DeclareNameFormat{author}{%
  \ifblank{#5}{}{#5\addspace}% prefix if applicable
  #1% last name
  \edef\firstname{#3}%
  \ifblank{#3}{}{\addcomma\addspace\expandafter\first{\firstname}}%
  \ifthenelse{\value{listcount}<\value{liststop}}%
   {\addslash}{}%
}

Note that for author = {Doe, John Arthur Kyle} in the bib file, #3 actually consists of John\bibnamedelimb Arthur\bibnamedelima Kyle, so we need to eliminate these for the \first macro to work.

EDIT: a "proper" NameFormat should include deliminators for multiple names, thus we check if we are in the middle of a list of names and if so print a slash.

Additionally, the authoryear style uses labelname to display the author name in citations, so that format should be changed to keep the formatting of the citation in line with that of the bibliography entry:

\DeclareNameFormat{labelname}{%
  \ifblank{#5}{}{#5\addspace}% prefix if applicable
  #1% last name
  \edef\firstname{#3}%
  \ifblank{#3}{}{\addcomma\addspace\expandafter\first{\firstname}}%
  \ifthenelse{\value{listcount}<\value{liststop}}%
   {\addslash}{}%
}

To summarize: This code

\documentclass{scrartcl}

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

\usepackage[T1]{fontenc}

\def\bibnamedelima{ }%
\def\bibnamedelimb{ }%
\DeclareNameFormat{author}{%
  \ifblank{#5}{}{#5\addspace}% prefix if applicable
  #1% last name
  \edef\firstname{#3}%
  \ifblank{#3}{}{\addcomma\addspace\expandafter\first{\firstname}}%
  \ifthenelse{\value{listcount}<\value{liststop}}%
   {\addslash}{}%
}

\DeclareNameFormat{labelname}{%
  \ifblank{#5}{}{#5\addspace}% prefix if applicable
  #1% last name
  \edef\firstname{#3}%
  \ifblank{#3}{}{\addcomma\addspace\expandafter\first{\firstname}}%
  \ifthenelse{\value{listcount}<\value{liststop}}%
   {\addslash}{}%
}

\makeatletter
\def\@empty{}
\def\first#1{\expandafter\@first#1 \@nil}
\def\@first#1 #2\@nil{#1\addspace%
  \if\relax\detokenize{#2}\relax\else\@initials#2\@nil\fi}
\def\initials#1{\expandafter\@initials#1 \@nil}
\def\@initials#1 #2\@nil{%
  \initial{#1}%
  \def\NextName{#2}%
  \ifx\@empty\NextName\relax%
  \else\@initials#2\@nil\fi}
\def\initial#1{\expandafter\@initial#1\@nil}
\def\@initial#1#2\@nil{#1.\addspace}
\makeatother

\begin{document}

\cite[123]{Doe}\par
\cite[124]{Doe2}\par
\cite[125]{vD}
\printbibliography

\end{document}

together with this bib file:

@book{Doe,
    title = {The secret life of John Doe},
    author = {Doe, John Arthur Kyle and Jane Emma Dane and Someone Else},
    year = {2013}
}

@book{Doe2,
    title = {The secret life of John Doe 2},
    author = {Doe, John},
    year = {2013}
}

@book{vD,
    title = {The secret life of John von Doe},
    author = {John Arthur Kyle von Doe},
    year = {2013}
}

produces this output:

cropped pdf output

EDIT: For more details on splitting strings, see e.g. the answers to this question; for information on macros using "strange" argument delimiters, see e.g. this thread.

  • Since you provided such a nice solution, wouldn't that be something worth integrating into biblatex as a further option to firstinits=true? (Has someone already suggested this to the maintainer of biblatex?) – ClintEastwood Sep 25 '14 at 4:34
8

Assuming that such cases are known abbreviations, I would do this with a datasource mapping like this (in your preamble):

\DeclareSourcemap{
  \maps[datatype=bibtex]{
    \map{
      \step[fieldsource=author,
            match={John Arthur Kyle},
            replace={John A. K.}]
    }
  }
}

This won't change your datasource, it does the mapping as the data is read. It's best to let Perl (which is what biber is written in) handle regexps and string manipulation - TeX is horrible for this.

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.