使用 Zref 包在 2 个卷之间进行智能交叉引用

使用 Zref 包在 2 个卷之间进行智能交叉引用

关注该帖子使用 xr-hyper 包制作多卷书时如何启用智能参考?我尝试使用zref@Andrew Swann 建议的包来详细说明所需的解决方案。不幸的是,我遇到了另一个问题,似乎是 中的一个错误zref。所以我决定在这里发布问题描述。我不确定这是否是发布此类问题的合适地方,但 的作者 Heiko Oberdiekzref没有回复我的电子邮件。

根据@Andrew Swann的建议,我尝试使用 Heiko 的软件包在多卷书的两卷之间提供交叉引用zref。此外,我引入了一个属性chaptervalue以提供智能引用,当方程式来自引用它的同一章节时,它会隐藏方程式编号的章节部分。这是 MWE。它包含 3 个文件。

通用代码保存在test-zref-common.tex

% Load packages abd declare external docs.
\usepackage[user,xr]{zref}
\ifnum\Volume=1
    % comment the line below to avoid errors
    \zexternaldocument{test-zref-2}% <============
    \makeatletter
        \zref@ifpropundefined{volume}{
            \zref@newprop{volume}{\Volume}
            \zref@newprop{chaptervalue}{\the\value{chapter}}
        }{}
        \zref@localaddprops{main}{volume,chaptervalue}
    \makeatother
\else
    \zexternaldocument{test-zref-1}
    \makeatletter
        \zref@ifpropundefined{volume}{
            \zref@newprop{volume}{\Volume}
            \zref@newprop{chaptervalue}{\the\value{chapter}}
        }{}
        \zref@localaddprops{main}{volume,chaptervalue}
    \makeatother
\fi

% Reset default equation numbering
\usepackage{amsmath}
\numberwithin{equation}{chapter}
\renewcommand{\theequation}{\arabic{equation}}

% Define \sref and \seqref macros for smart cross-references of equations
\makeatletter
\newcommand\ifcurrentchapter[3]{%
  \def\temp@a{\number\value{chapter}}%
  \def\temp@b{\zref@extract{#1}{chaptervalue}}%
  \if\temp@a\temp@b%
    #2%
  \else%
    #3%
  \fi%
}
\newcommand{\sref}[1]{\hbox{\ifcurrentchapter{#1}{}{\zref[chaptervalue]{#1}.}\zref{#1}}}
\newcommand{\seqref}[1]{(\sref{#1})}
\makeatother

% Define a macro to print test text
\newcommand{\testtext}{
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:1}. Equal: \ifcurrentchapter{ch:1}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:2}. Equal: \ifcurrentchapter{ch:2}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:17}. Equal: \ifcurrentchapter{ch:17}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:18}. Equal: \ifcurrentchapter{ch:18}{Yes}{No}
}

普通文件由第 1 卷读取(test-zref-1.tex

\documentclass[oneside]{book}
\newcommand{\Volume}{1}
\input{test-zref-common}

\begin{document}
\chapter{1 in Volume 1}
\label{ch:1}\zlabel{ch:1}

\testtext

\begin{equation}
  eq1
  \label{1.1}\zlabel{1.1}
\end{equation}
\begin{equation}
  eq2
  \label{1.2}\zlabel{1.2}
\end{equation}

\seqref{1.1}, \seqref{1.2}; \seqref{2.1}, \seqref{2.2}.
\seqref{17.1}, \seqref{17.2}; \seqref{18.1}, \seqref{18.2}.

\chapter{2  in Volume 2}
\label{ch:2}\zlabel{ch:2}

\testtext

\begin{equation}
  eq3
  \label{2.1}\zlabel{2.1}
\end{equation}

\begin{equation}
  eq4
  \label{2.2}\zlabel{2.2}
\end{equation}

\seqref{1.1}, \seqref{1.2}; \seqref{2.1}, \seqref{2.2}.
\seqref{17.1}, \seqref{17.2}; \seqref{18.1}, \seqref{18.2}.
\end{document} 

第 2 卷(test-zref-1.tex):

%\documentclass{scrbook}
\documentclass[oneside]{book}
\newcommand{\Volume}{2}
\setcounter{chapter}{16}
\input{test-zref-common}

\begin{document}

\chapter{1 in Volume 2}
\label{ch:17}\zlabel{ch:17}

\testtext

\begin{equation}
  eq1
  \label{17.1}\zlabel{17.1}
\end{equation}

\begin{equation}
  eq2
  \label{17.2}\zlabel{17.2}
\end{equation}

\seqref{1.1}, \seqref{1.2}; \seqref{2.1}, \seqref{2.2}.
\seqref{17.1}, \seqref{17.2}; \seqref{18.1}, \seqref{18.2}.

\chapter{2  in Volume 2}
\label{ch:18}\zlabel{ch:18}

\testtext

\begin{equation}
  eq3
  \label{18.1}\zlabel{18.1}
\end{equation}

\begin{equation}
  eq4
  \label{18.2}\zlabel{18.2}
\end{equation}

\seqref{1.1}, \seqref{1.2}; \seqref{2.1}, \seqref{2.2}.
\seqref{17.1}, \seqref{17.2}; \seqref{18.1}, \seqref{18.2}.
\end{document} 

如果我从卷 #2 引用卷 #1,则效果很好(即当行

\zexternaldocument{test-zref-2}

已从 中删除test-zref-common.tex)。但是,当我尝试引用两个卷(从卷 #2 引用卷 #1 以及从卷 #1 引用卷 #2)时,它会失败。zref抱怨该chaptervalue属性已定义。附件演示了此问题。

这是 MWE 中的一个 bugzref还是一个错误?

答案1

这些错误都存在于您的代码中,都在通用文件中。首先,您应该在指定外部文档之前定义属性。其次,您需要在测试中使用\ifnumnot 。以下是修改后的通用文件:\if

% Load packages abd declare external docs.
\usepackage[user,xr]{zref}
\makeatletter
\zref@newprop{volume}{\Volume}
\zref@newprop{chaptervalue}{\the\value{chapter}}
\zref@localaddprops{main}{volume,chaptervalue}
\makeatother
\ifnum\Volume=1
    \zexternaldocument{test-zref-2}% <============
\else
    \zexternaldocument{test-zref-1}
\fi

% Reset default equation numbering
\usepackage{amsmath}
\numberwithin{equation}{chapter}
\renewcommand{\theequation}{\arabic{equation}}

% Define \sref and \seqref macros for smart cross-references of equations
\makeatletter
\newcommand\ifcurrentchapter[3]{%
  \def\temp@a{\number\value{chapter}}%
  \def\temp@b{\zref@extract{#1}{chaptervalue}}%
  \if\relax\temp@a\else\if\relax\temp@b\else
  \ifnum\temp@a=\temp@b%
    #2%
  \else%
    #3%
  \fi%
  \fi\fi
}
\newcommand{\sref}[1]{\hbox{\ifcurrentchapter{#1}{}{\zref[chaptervalue]{#1}.}\zref{#1}}}
\newcommand{\seqref}[1]{(\sref{#1})}
\makeatother

% Define a macro to print test text
\newcommand{\testtext}{
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:1}. Equal: \ifcurrentchapter{ch:1}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:2}. Equal: \ifcurrentchapter{ch:2}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:17}. Equal: \ifcurrentchapter{ch:17}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:18}. Equal: \ifcurrentchapter{ch:18}{Yes}{No}
}

这将在第二个文档的第 17 章中产生以下页面:

Sample output

答案2

扩展了 @Andrew Swann 给出的答案,我在公共块中更新了他的代码,以避免在第一次运行 LaTeX 时在源文件上生成错误,因为标签的值尚不清楚。这里的关键点是应该用chaptervalue默认值定义属性。我认为它等于-1。然后,\ifcurrentchapter可以修改宏以检查是否\temp@b为负数,就像第一次运行时一样。此外,我添加了hyperrefxr-hyper包,以便允许在书中的卷之间进行超引用。

以下是最终版本test-zref-common.tex

% Load packages and declare external docs.
\usepackage{xr-hyper}%                     <== load xr-hyper package
\usepackage[unicode,colorlinks]{hyperref}% <== load hyperref package
\usepackage[user,xr]{zref}
\makeatletter
\zref@newprop{volume}{\Volume}
\zref@newprop{chaptervalue}[-1]{\the\value{chapter}}% <= note the default value [-1]
\zref@localaddprops{main}{volume,chaptervalue}
\makeatother
\ifnum\Volume=1
    \externaldocument{test-zref-2}%  <== declare external doc for xr-hyper
    \zexternaldocument{test-zref-2}% <== declare external doc for zref
\else
    \externaldocument{test-zref-1}
    \zexternaldocument{test-zref-1}
\fi

% Reset default equation numbering
\usepackage{amsmath}
\numberwithin{equation}{chapter}
\renewcommand{\theequation}{\arabic{equation}}

% Define \sref and \seqref macros for smart cross-references of equations
\makeatletter
\newcommand\ifcurrentchapter[3]{%
  \def\temp@a{\number\value{chapter}}%
  \def\temp@b{\zref@extract{#1}{chaptervalue}}%
  \ifnum\temp@a=\temp@b%
    #2%
  \else%
    \ifnum\temp@b<0
      #2%
    \else
      #3%
    \fi%
  \fi%
}
%\newcommand{\sref}[1]{\hbox{\ifcurrentchapter{#1}{}{\zref[chaptervalue]{#1}.}\zref{#1}}}
% note \hyperref in the definition of \sref
\newcommand{\sref}[1]{\hyperref[#1]{\hbox{\ifcurrentchapter{#1}{}{\zref[chaptervalue]{#1}.}\zref{#1}}}}
\newcommand{\seqref}[1]{(\sref{#1})}
%\newcommand{\seqref}[1]{(\hyperref[#1]{\hbox{\sref{#1}}})}
\makeatother

% Define a macro to print test text
\newcommand{\testtext}{
    Chapter \sref{ch:1}, Chapter \sref{ch:2},
    Chapter \sref{ch:17}, Chapter \sref{ch:18}.
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:1}. Equal: \ifcurrentchapter{ch:1}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:2}. Equal: \ifcurrentchapter{ch:2}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:17}. Equal: \ifcurrentchapter{ch:17}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:18}. Equal: \ifcurrentchapter{ch:18}{Yes}{No}
    \par
    \seqref{1.1}, \seqref{1.2}; \seqref{2.1}, \seqref{2.2}.
    \par
    \seqref{17.1}, \seqref{17.2}; \seqref{18.1}, \seqref{18.2}.
}

\endinput

相关内容