Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I have a question about unresolved references (I'm using natbib and pdflatex/bibtex) and the default behavior to print a (?). What I would like is the following:

  1. The (?) replaced with (citation-key) (only for missing references), and
  2. A list of the missing citation keys to be printed somewhere in the resulting pdf (e.g., at the beginning of the reference list).

I've read this question about using the showkeys package, but the result is not really what I'm looking for because (1) it doesn't replace the (?) but just prints the citation key over the top, (2) it seems to do this for all references, and I just want the missing ones, and (3) it doesn't produce the list of missing references.

Here's a minimum example (though I suspect it may not necessary for this question).

\documentclass{article}
\usepackage{natbib}
%\usepackage{showkeys} % not what I'm looking for
\bibpunct{(}{)}{;}{a}{}{,}

\title{Example}    
\author{Me}

\begin{document}    
\maketitle

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Mauris vel sem id nulla cursus vulputate at et erat \citep{Author2001}.
Nunc rutrum nibh lorem, eget posuere nibh sollicitudin vitae \citep{Author1993}.

\bibliography{Example}    
\end{document}

I'm completely open to new packages, as well as ways of parsing the example.log file to extract the lines, like:

Package natbib Warning: Citation `Author2001' on page 1 undefined on input line
14.
share|improve this question
3  
biblatex prints the citation key for undefined references by default, if switching to that is an option. –  Torbjørn T. Jul 8 '13 at 12:25
    
@TorbjørnT. Thanks, I'll look into that. –  Thomas Jul 8 '13 at 18:06

1 Answer 1

up vote 4 down vote accepted

I have addressed the following points:

  1. Find out those references which are not in the reference list. (Not asked in this question.)
  2. Find out those references which were not cited.
  3. Replace missing reference (?) with citation key.
\documentclass{article}
\usepackage{natbib}
%\usepackage{showkeys} % not what I'm looking for
\bibpunct{(}{)}{;}{a}{}{,}

\makeatletter
\let\oldcitation\citation
\def\xcomma{}
\def\bibList{}
\def\citation#1{%
    \@for\xx:=#1\do{%
      \expandafter\ifx\csname bbl@\xx\endcsname\relax%
        \expandafter\gdef\csname bbl@\xx\endcsname{0}%
        \xdef\bibList{\bibList\xcomma\xx}%
        \def\xcomma{,}%
      \fi%
    }%
    \oldcitation{#1}%
}
\AtEndDocument{\@bsphack
  \protected@write\@auxout{}%
         {\string\BibList{\bibList}}%
  \@esphack}
\def\xComma{}
\def\biblostkeys{}
\def\BibList#1{%
   \@for\xx:=#1\do{%
      \expandafter\ifx\csname BBL@\xx\endcsname\relax%
        \xdef\biblostkeys{\biblostkeys\xComma\xx}%
        \def\xComma{,\space}%
      \fi%
   }%
}
\def\refnotcalled{}
\def\Xcomma{}
\let\oldbibcite\bibcite
\def\bibcite#1{%
   \expandafter\gdef\csname BBL@#1\endcsname{0}%
   \expandafter\ifx\csname bbl@#1\endcsname\relax% Not cited
     \xdef\refnotcalled{\refnotcalled\Xcomma#1}%
     \def\Xcomma{,\space}%
   \fi%
   \oldbibcite{#1}%
}
\def\NAT@citex%
  [#1][#2]#3{%
  \NAT@reset@parser
  \NAT@sort@cites{#3}%
  \NAT@reset@citea
  \@cite{\let\NAT@nm\@empty\let\NAT@year\@empty
    \@for\@citeb:=\NAT@cite@list\do
    {\@safe@activestrue
     \edef\@citeb{\expandafter\@firstofone\@citeb\@empty}%
     \@safe@activesfalse
     \@ifundefined{b@\@citeb\@extra@b@citeb}{\@citea%
       {\reset@font\bfseries\@citeb}\NAT@citeundefined
                 \PackageWarning{natbib}%
       {Citation `\@citeb' on page \thepage \space undefined}\def\NAT@date{}}%
     {\let\NAT@last@nm=\NAT@nm\let\NAT@last@yr=\NAT@year
      \NAT@parse{\@citeb}%
      \ifNAT@longnames\@ifundefined{bv@\@citeb\@extra@b@citeb}{%
        \let\NAT@name=\NAT@all@names
        \global\@namedef{bv@\@citeb\@extra@b@citeb}{}}{}%
      \fi
     \ifNAT@full\let\NAT@nm\NAT@all@names\else
       \let\NAT@nm\NAT@name\fi
     \ifNAT@swa\ifcase\NAT@ctype
       \if\relax\NAT@date\relax
         \@citea\NAT@hyper@{\NAT@nmfmt{\NAT@nm}\NAT@date}%
       \else
         \ifx\NAT@last@nm\NAT@nm\NAT@yrsep
            \ifx\NAT@last@yr\NAT@year
              \def\NAT@temp{{?}}%
              \ifx\NAT@temp\NAT@exlab\PackageWarningNoLine{natbib}%
               {Multiple citation on page \thepage: same authors and
               year\MessageBreak without distinguishing extra
               letter,\MessageBreak appears as question mark}\fi
              \NAT@hyper@{\NAT@exlab}%
            \else\unskip\NAT@spacechar
              \NAT@hyper@{\NAT@date}%
            \fi
         \else
           \@citea\NAT@hyper@{%
             \NAT@nmfmt{\NAT@nm}%
             \hyper@natlinkbreak{%
               \NAT@aysep\NAT@spacechar}{\@citeb\@extra@b@citeb
             }%
             \NAT@date
           }%
         \fi
       \fi
     \or\@citea\NAT@hyper@{\NAT@nmfmt{\NAT@nm}}%
     \or\@citea\NAT@hyper@{\NAT@date}%
     \or\@citea\NAT@hyper@{\NAT@alias}%
     \fi \NAT@def@citea
     \else
       \ifcase\NAT@ctype
        \if\relax\NAT@date\relax
          \@citea\NAT@hyper@{\NAT@nmfmt{\NAT@nm}}%
        \else
         \ifx\NAT@last@nm\NAT@nm\NAT@yrsep
            \ifx\NAT@last@yr\NAT@year
              \def\NAT@temp{{?}}%
              \ifx\NAT@temp\NAT@exlab\PackageWarningNoLine{natbib}%
               {Multiple citation on page \thepage: same authors and
               year\MessageBreak without distinguishing extra
               letter,\MessageBreak appears as question mark}\fi
              \NAT@hyper@{\NAT@exlab}%
            \else
              \unskip\NAT@spacechar
              \NAT@hyper@{\NAT@date}%
            \fi
         \else
           \@citea\NAT@hyper@{%
             \NAT@nmfmt{\NAT@nm}%
             \hyper@natlinkbreak{\NAT@spacechar\NAT@@open\if*#1*\else#1\NAT@spacechar\fi}%
               {\@citeb\@extra@b@citeb}%
             \NAT@date
           }%
         \fi
        \fi
       \or\@citea\NAT@hyper@{\NAT@nmfmt{\NAT@nm}}%
       \or\@citea\NAT@hyper@{\NAT@date}%
       \or\@citea\NAT@hyper@{\NAT@alias}%
       \fi
       \if\relax\NAT@date\relax
         \NAT@def@citea
       \else
         \NAT@def@citea@close
       \fi
     \fi
     }}\ifNAT@swa\else\if*#2*\else\NAT@cmt#2\fi
     \if\relax\NAT@date\relax\else\NAT@@close\fi\fi}{#1}{#2}}

\title{Example}    
\author{Me}

\begin{document}    
\maketitle

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Mauris vel sem id nulla cursus vulputate at et erat \citep{Author2001}.
Nunc rutrum nibh lorem, eget posuere nibh sollicitudin vitae \citep{Author2001,Author1993}.
Nunc rutrum nibh lorem, eget posuere nibh sollicitudin vitae \citep{Author1993}.

\noindent\fbox{Keys not in reference list: \biblostkeys} % Keys which are not in reference list

\begin{thebibliography}{99}
\bibitem[Author(2001)]{Author2001} Author (2001).

%not cited
\bibitem[Author(2004)]{Author2004} Author (2004).

%not cited
\bibitem[Author(2005)]{Author2005} Author (2005).

\end{thebibliography}

\noindent\fbox{Keys not cited in text: \refnotcalled} % Keys which are not cited in text

\end{document}

You need to compile three times to get everything right. See the commands \biblostkeys and refnotcalled.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.