与“xr”包和最终的PDF组合交叉引用?

与“xr”包和最终的PDF组合交叉引用?

到目前为止,我在 Overleaf 中使用交叉引用来自 StackExchange 的这个想法,并已在 Overleaf 中进行了改编这里。我的问题是,当我最终将main.tex和合并SI.tex为一个 PDF 文件时,该如何操作?或者最好使用软件包subfiles

我需要一种方法来将这些文件放在一个 PDF 中,同时仍使交叉引用起作用。当然,从外部合并它们会导致引用跳转失败。

答案1

您所说的将两个 .tex 文件(即两个文档的 TeX 源代码)合并为一个 .pdf 文件究竟是什么意思?您考虑的工作流程是什么?
我之所以问这个问题,是因为源代码和生成的 .pdf 文件是不同的东西。

是因为它可能。

如果 overleaf 也可以生成 .dvi 文件而不是 .pdf 文件,并且您可以运行程序dviconcatdvipdfmdvipdfmx,则连接文档并创建 .pdf 文件可能是可行的。

连接文件时可能会遇到的一个问题是超链接目标的名称:

使用 hyperref 包通过 LaTeX 创建所有 .pdf 文件时,不同的 .pdf 文件可能具有相同名称的命名目标。(目标的名称通常来自创建相关目标时 LaTeX 计数器的名称和这些计数器的值。)因此,需要采取措施确保该 .pdf 文件中通过连接而产生的超链接的目标名称的唯一性。

作为确保目标名称唯一性的一种手段,hyperref 包现在具有 -feature \HyperDestNameFilter

\HyperDestNameFilter在第 3.2 节中解释了目的地名称的选项hyperref 包手册

以下是该部分的引文:

如果最终的 PDF 文件要与另一个文件合并,则目标名称可能会发生冲突,因为两个文档可能包含chapter.1page.1。还在文档开头 hyperref设置带有名称的锚点。这可以通过重新定义 来解决。包每次调用此宏时,它都会使用目标名称。宏必须是可扩展的,并且期望目标名称作为唯一参数。例如,重新定义宏以向所有目标名称添加前缀:Doc-Start\HyperDestNameFilterhyperref

\renewcommand*{\HyperDestNameFilter}[1]{\jobname-#1}

在文档中,docA目的地名称chapter.2变成docA-chapter.2

连接 .pdf 文件时可能遇到的另一个问题是连接的文件之间的交叉引用。

到目前为止,我发现的解决这个问题的唯一方法不是从单个 .tex 文档创建 .pdf 文件,而是在使用 dvipdfm 或 dvipdfmx 驱动程序选项加载 hyperref 时创建 .dvi 文件。

然后,您可以使用程序 dviconcat(dviconcat 是许多 TeX 发行版的一部分,例如 texlive 和 MiKTeX)连接单个 .dvi 文件,然后使用 dvipdfm 程序或 dvipdfmx 程序(也是许多 TeX 发行版的一部分)将生成的 .dvi 文件转换为 .pdf 文件。

(我也尝试了 dvips-route,但是没有成功。)

而不是負責-package 你需要使用xr-hyper-package 并且在创建 .dvi 文件进行连接时,您需要重新定义\XR@@dURL\HyperDestNameFilter考虑 -prefix 并忽略\XR@URL(包含外部文件的 url)那些要与当前文档连接的外部文档。

在下面的例子中

  • 所有要连接的文档都必须使用\HyperDestNameFilter-prefix。
  • 没有两个文档可以具有相同的\HyperDestNameFilter-prefix。
  • 假设所有要连接的文件都使用不同的\HyperDestNameFilter前缀,这些前缀的共同点是它们都包含短语MyDocument,而目标名称本身可能不包含该短语。因此,宏将目标名称中
    是否存在短语作为指示,以决定是否需要附加前缀:MyDocument\HyperDestNameFilter\HyperDestNameFilter
  • \HyperDestNameFilter仅当目的地名称既不包含短语MyDocument也不包含标记时\empty,才(重新)定义为附加前缀。
  • 提供额外的基础设施xr-hyper的命令\externaldocument
    1. 该命令\SetNextExternalFilesHyperDestNameFilterPrefix{...}用于指定\HyperDestNameFilter在创建相关外部文档时使用的 -prefix。(如果没有\HyperDestNameFilter使用 -prefix,则可以指定\SetNextExternalFilesHyperDestNameFilterPrefix{\empty}。)
    2. 命令\UseURL\DoNotUseURL。这些命令用于指定是否\externaldocument应考虑包含外部文档的 .pdf 文件的 URL。(如果 URL 偏离了 的\externaldocument第一个非可选参数 + .pdf/文件扩展名\externaldocument,可以在的最后一个可选参数中指定 URL 。)
      对于要与当前文档连接的外部文档,不应考虑 URL。
      对于不与当前文档连接的外部文档,应考虑 URL。(URL 指定包含相关外部文档的 .pdf 文件的 URL。)
  • \XR@@dURL被重新定义
    • 能够忽略包含相关外部文档的 .pdf 文件的 URL:
      如果\externaldocument相关命令前面有 ,则URL 会被忽略\DoNotUseURL
      如果相关\externaldocument命令前面有 ,则 URL 不会被忽略\UseURL
    • 将与所讨论的外部文档一起使用的 -prefix附加到参数#4(该参数表示与所讨论的外部引用标签相连的命名目的地的名称) 。\HyperDestNameFilter
  • 每个\externaldocument用于导入与当前文档连接的外部文档的引用数据的命令都必须与一个命令\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument...}和一个命令一起使用\DoNotUseURL
  • 每条\externaldocument用于导入外部文档的引用数据的命令(该外部文档不与当前文档连接)都必须附带一条命令,该命令用于提供有关创建相关外部文档时使用的前缀的\SetNextExternalFilesHyperDestNameFilterPrefix{...}信息,并附带一条命令。如果在创建此类文件时未使用 HyperDestNameFilter-Prefix,则可以指定。\HyperDestNameFilter\UseURL\SetNextExternalFilesHyperDestNameFilterPrefix{\empty}

下面的例子是用三个文档来形成一个场景。

第一个文档的标题是“我的文档 1”。
包含第一个文档源代码的文件是MyDocument1.tex

第二个文档的标题是“我的文档 2”。
包含第二个文档源代码的文件是MyDocument2.tex

第三个文档的标题是“我的文档 3”。
包含第三个文档源代码的文件是MyDocument3.tex

文档“我的文档 1”和“我的文档 2”最终将保存在 .pdf 文件中MyDocument1and2.pdf

文档“我的文档 3”将保持单独状态并最终保存在 .pdf 文件中MyDocument3.pdf

编译/连接指令:

在同一目录中有MyPatches.texMyDocument1.texMyDocument2.tex以及。MyDocument3.tex

使该目录成为活动目录/当前目录/任何其他目录。

交替编译MyDocument1.tex、、使用MyDocument2.tex,直到 和和都存在于该目录中,并且和和既不包含再次运行 latex 的请求,也不包含有关未定义引用的警告。MyDocument3.texlatexMyDocument1.dviMyDocument2.dviMyDocument3.dviMyDocument1.logMyDocument2.logMyDocument3.log

调用程序将和dviconcat连接到:MyDocument1.dviMyDocument2.dviMyDocument1and2.dvi
dviconcat -o MyDocument1and2.dvi MyDocument1.dvi MyDocument2.dvi

要求dvipdfmx转换MyDocument1and2.dviMyDocument1and2.pdf
dvipdfmx MyDocument1and2.dvi

要求dvipdfmx转换MyDocument3.dviMyDocument3.pdf
dvipdfmx MyDocument3.dvi

如果一切顺利的话,

  • MyDocument1and2.pdf应由“我的文档 1”和“我的文档 2”的内容组成。MyDocument1and2.pdf“我的文档 1”和“我的文档 2”之间的交叉引用应导致在 内导航MyDocument1and2.pdf。“我的文档 3”内的交叉引用MyDocument1and2.pdf应导致在 内打开并显示和滚动MyDocument3.pdf
  • MyDocument3.pdf应由“我的文档 3”的内容组成。MyDocument3.pdf对“我的文档 1”或“我的文档 2”的交叉引用应导致加载并在其中显示和滚动MyDocument1and2.pdf

MyPatches.tex

%%====================================================================
%% Fixes for hyperref-drivers xetex and dvipdfm/dvipdfmx - apply them
%% _after_ loading the hyperref package:
%%====================================================================
\begingroup
\def\tempa{hxetex}%
\ifx\Hy@driver\tempa\expandafter\@secondoftwo\else\expandafter\@firstofone\fi
{%
  \def\tempa{hdvipdfm}%
  \ifx\Hy@driver\tempa\expandafter\@firstofone\else\expandafter\endgroup\expandafter\@gobble\fi
}{%
  \endgroup
  %%--------------------------------------------------------------------
  %% Fix hxetex's and hdvipdfm's  \hyper@linkfile  by adding a group for
  %% preventing erroneous warnings
  %%
  %%  Package hyperref Warning: Invalid page number (0)
  %%  (hyperref)                for remote PDF file.
  %%  (hyperref)                Using page 1 on input line ...
  %%
  %% For more information see:
  %%  <https://github.com/latex3/hyperref/issues/107#issue-513025725>
  %%--------------------------------------------------------------------
  \def\hyper@linkfile#1#2#3{%
    \begingroup % <--- \begingroup inserted
    \leavevmode
    \Hy@BeginAnnot{%
      \def\Hy@pstringF{#2}%
      \Hy@CleanupFile\Hy@pstringF
      \Hy@pstringdef\Hy@pstringF\Hy@pstringF
      \Hy@pstringdef\Hy@pstringD{#3}%
      \Hy@MakeRemoteAction %<-- Without the group the effects of \Hy@MakeRemoteAction 
                           %    will be global, causing erroneous warnings.
      \@pdfm@mark{%
        bann<<%
          /Type/Annot%
          /Subtype/Link%
          \ifHy@pdfa /F 4\fi
          \Hy@setpdfborder
          \Hy@setpdfhighlight
          \ifx\@filebordercolor\relax
          \else
            /C[\@filebordercolor]%
          \fi
          /A<<%
            /S/GoToR%
            /F(\Hy@pstringF)%
            /D%
            \ifx\\#3\\%
              [\Hy@href@page\@pdfremotestartview]%
            \else
              (\Hy@pstringD)%
            \fi
            \Hy@SetNewWindow
            \Hy@href@nextactionraw
          >>%
        >>%
      }%
      \Hy@colorlink\@filecolor
    }%
    #1\Hy@xspace@end
    \Hy@EndAnnot
    \endgroup % <--- \endgroup inserted
  }%
  %%--------------------------------------------------------------------
  %% Add special for making named destinations reachable from "outside":
  %% For more information see:
  %%  <https://tug.org/pipermail/dvipdfmx/2019-May/000003.html>
  %%--------------------------------------------------------------------
  \special{dvipdfmx:config C 0x10}%
}%
%%=============================================================================
%% Additional infrastructure for xr-hyper's \externaldocument so you can
%% specify 
%% - external files' \HyperDestNameFilter-pefix
%% - whether URLs of external files shall be used or not be used.
%%   (They shall not be used when dvi-files get concatenated via dviconcat
%%    before converting to pdf.)
%%=============================================================================
%%-----------------------------------------------------------------------------
%% Fork whether argument contains the phrase "MyDocument"
%%.............................................................................
\@ifdefinable\UD@GobbleToMyDocument{\long\def\UD@GobbleToMyDocument#1MyDocument{}}%
\newcommand\UD@CheckWhetherNoMyDocument[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToMyDocument#1MyDocument}%
}%
%%-----------------------------------------------------------------------------
%% Fork whether argument contains the token "\empty"
%%.............................................................................
\@ifdefinable\UD@GobbleToEmpty{\long\def\UD@GobbleToEmpty#1\empty{}}%
\newcommand\UD@CheckWhetherNoEmpty[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToEmpty#1\empty}%
}%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
  {\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%%--------------------------------------------------------------------
%% A place-holder for external files'  \HyperDestNameFilter-pefix
%%.............................................................................
\newcommand\NextExternalFilesHyperDestNameFilterPrefix{}%
%%-----------------------------------------------------------------------------
%% Set external files'  \HyperDestNameFilter-pefix
%%.............................................................................
\newcommand\SetNextExternalFilesHyperDestNameFilterPrefix[1]{%
 \renewcommand\NextExternalFilesHyperDestNameFilterPrefix{#1}%
}%
%%-----------------------------------------------------------------------------
%% Take into account URL of external file/
%% don't take into account URL of external file.
%%.............................................................................
\newcommand\UseURL{\global\DontUseURLfalse}%
\newcommand\DoNotUseURL{\global\DontUseURLtrue}%
\newif\ifDontUseURL
%%-----------------------------------------------------------------------------
%% Change \XR@@dURL to take the \HyperDestNameFilter-prefix of the external file
%% into account and to omit \XR@URL
%%-----------------------------------------------------------------------------
\def\XR@@dURL#1#2#3#4#5\\{%
  {#1}{#2}%
  \if!#4!%
  \else
    {#3}{\NextExternalFilesHyperDestNameFilterPrefix#4}%
    \ifDontUseURL{}\else{\XR@URL}\fi
  \fi
}%

MyDocument1.tex

\documentclass{article}

\usepackage{xr-hyper}
\usepackage[dvipdfmx]{hyperref}

\makeatletter
\input MyPatches.tex
%%-----------------------------------------------------------------------------
%% Change \HyperDestNameFilter to add the prefix "MyDocument1-" in case the name
%% of the destination doses not already contain the phrase "MyDocument" or the 
%% token "\empty":
%%
%% !!!! The \HyperDestNameFilter-prefix varies from file to file/
%% !!!! from document to document
%%.............................................................................
\renewcommand*{\HyperDestNameFilter}[1]{%
  \UD@CheckWhetherNoEmpty{#1}{\UD@CheckWhetherNoMyDocument{#1}{MyDocument1-}{}}{}#1%
}%
%%-----------------------------------------------------------------------------
\makeatother

\DoNotUseURL
\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument2-}%
\externaldocument[MyDocument2-]{MyDocument2}[MyDocument1and2.pdf]%

\UseURL
\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument3-}%
\externaldocument[MyDocument3-]{MyDocument3}%


\begin{document}

\title{My Document 1}
\author{Me, Myself and I}    
\maketitle
\newpage

\section{First section of My Document 1}
\label{LabelInMyDocument1}

\noindent
The source code of \textbf{My Document 1} is contained in \textbf{MyDocument1.tex.}\\
The source code of section \textbf{First section of My Document 1} contains
the referencing-label \textbf{LabelInMyDocument1}.\\
The target-file of \textbf{My Document 1} will be \textbf{MyDocument1and2.pdf}.\\

\bigskip\noindent
The source code of \textbf{My Document 2} is contained in \textbf{MyDocument2.tex.}\\
The source code of section \textbf{First section of My Document 2} contains
the referencing-label \textbf{LabelInMyDocument2}.\\
The target-file of \textbf{My Document 2} will be \textbf{MyDocument1and2.pdf}.\\

\bigskip\noindent
The source code of \textbf{My Document 3} is contained in \textbf{MyDocument3.tex.}\\
The source code of section \textbf{First section of My Document 3} contains
the referencing-label \textbf{LabelInMyDocument3}.\\
The target-file of \textbf{My Document 3} will be \textbf{MyDocument3.pdf}.\\


\bigskip\noindent
\textbf{Referencing}

\bigskip\noindent
\verb|\ref{LabelInMyDocument1}| yields:\ref{LabelInMyDocument1}\\
\verb|\pageref{LabelInMyDocument1}| yields:\pageref{LabelInMyDocument1}\\
\verb|\ref{MyDocument2-LabelInMyDocument2}| yields:\ref{MyDocument2-LabelInMyDocument2}\\
\verb|\pageref{MyDocument2-LabelInMyDocument2}| yields:\pageref{MyDocument2-LabelInMyDocument2}\\
\verb|\ref{MyDocument3-LabelInMyDocument3}| yields:\ref{MyDocument3-LabelInMyDocument3}\\
\verb|\pageref{MyDocument3-LabelInMyDocument3}| yields:\pageref{MyDocument3-LabelInMyDocument3}\\

\end{document}

MyDocument2.tex

\documentclass{article}

\usepackage{xr-hyper}
\usepackage[dvipdfmx]{hyperref}

\makeatletter
\input MyPatches.tex
%%-----------------------------------------------------------------------------
%% Change \HyperDestNameFilter to add the prefix "MyDocument2-" in case the name
%% of the destination doses not already contain the phrase "MyDocument" or the 
%% token "\empty":
%%
%% !!!! The \HyperDestNameFilter-prefix varies from file to file/
%% !!!! from document to document
%%.............................................................................
\renewcommand*{\HyperDestNameFilter}[1]{%
  \UD@CheckWhetherNoEmpty{#1}{\UD@CheckWhetherNoMyDocument{#1}{MyDocument2-}{}}{}#1%
}%
%%-----------------------------------------------------------------------------
\makeatother

\DoNotUseURL
\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument1-}%
\externaldocument[MyDocument1-]{MyDocument1}[MyDocument1and2.pdf]%

\UseURL
\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument3-}%
\externaldocument[MyDocument3-]{MyDocument3}%


\begin{document}

\title{My Document 2}
\author{Me, Myself and I}    
\maketitle
\newpage

\section{First section of My Document 2}
\label{LabelInMyDocument2}

\noindent
The source code of \textbf{My Document 1} is contained in \textbf{MyDocument1.tex.}\\
The source code of section \textbf{First section of My Document 1} contains
the referencing-label \textbf{LabelInMyDocument1}.\\
The target-file of \textbf{My Document 1} will be \textbf{MyDocument1and2.pdf}.\\

\bigskip\noindent
The source code of \textbf{My Document 2} is contained in \textbf{MyDocument2.tex.}\\
The source code of section \textbf{First section of My Document 2} contains
the referencing-label \textbf{LabelInMyDocument2}.\\
The target-file of \textbf{My Document 2} will be \textbf{MyDocument1and2.pdf}.\\

\bigskip\noindent
The source code of \textbf{My Document 3} is contained in \textbf{MyDocument3.tex.}\\
The source code of section \textbf{First section of My Document 3} contains
the referencing-label \textbf{LabelInMyDocument3}.\\
The target-file of \textbf{My Document 3} will be \textbf{MyDocument3.pdf}.\\


\bigskip\noindent
\textbf{Referencing}

\bigskip\noindent
\verb|\ref{MyDocument1-LabelInMyDocument1}| yields:\ref{MyDocument1-LabelInMyDocument1}\\
\verb|\pageref{MyDocument1-LabelInMyDocument1}| yields:\pageref{MyDocument1-LabelInMyDocument1}\\
\verb|\ref{LabelInMyDocument2}| yields:\ref{LabelInMyDocument2}\\
\verb|\pageref{LabelInMyDocument2}| yields:\pageref{LabelInMyDocument2}\\
\verb|\ref{MyDocument3-LabelInMyDocument3}| yields:\ref{MyDocument3-LabelInMyDocument3}\\
\verb|\pageref{MyDocument3-LabelInMyDocument3}| yields:\pageref{MyDocument3-LabelInMyDocument3}\\

\end{document}

MyDocument3.tex

\documentclass{article}

\usepackage{xr-hyper}
\usepackage[dvipdfmx]{hyperref}

\makeatletter
\input MyPatches.tex
%%-----------------------------------------------------------------------------
%% Change \HyperDestNameFilter to add the prefix "MyDocument3-" in case the name
%% of the destination doses not already contain the phrase "MyDocument" or the 
%% token "\empty":
%%
%% !!!! The \HyperDestNameFilter-prefix varies from file to file/
%% !!!! from document to document
%%.............................................................................
\renewcommand*{\HyperDestNameFilter}[1]{%
  \UD@CheckWhetherNoEmpty{#1}{\UD@CheckWhetherNoMyDocument{#1}{MyDocument3-}{}}{}#1%
}%
%%-----------------------------------------------------------------------------
\makeatother

\UseURL
\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument1-}%
\externaldocument[MyDocument1-]{MyDocument1}[MyDocument1and2.pdf]%

\UseURL
\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument2-}%
\externaldocument[MyDocument2-]{MyDocument2}[MyDocument1and2.pdf]%


\begin{document}

\title{My Document 3}
\author{Me, Myself and I}    
\maketitle
\newpage

\section{First section of My Document 3}
\label{LabelInMyDocument3}

\noindent
The source code of \textbf{My Document 1} is contained in \textbf{MyDocument1.tex.}\\
The source code of section \textbf{First section of My Document 1} contains
the referencing-label \textbf{LabelInMyDocument1}.\\
The target-file of \textbf{My Document 1} will be \textbf{MyDocument1and2.pdf}.\\

\bigskip\noindent
The source code of \textbf{My Document 2} is contained in \textbf{MyDocument2.tex.}\\
The source code of section \textbf{First section of My Document 2} contains
the referencing-label \textbf{LabelInMyDocument2}.\\
The target-file of \textbf{My Document 2} will be \textbf{MyDocument1and2.pdf}.\\

\bigskip\noindent
The source code of \textbf{My Document 3} is contained in \textbf{MyDocument3.tex.}\\
The source code of section \textbf{First section of My Document 3} contains
the referencing-label \textbf{LabelInMyDocument3}.\\
The target-file of \textbf{My Document 3} will be \textbf{MyDocument3.pdf}.\\


\bigskip\noindent
\textbf{Referencing}

\bigskip\noindent
\verb|\ref{MyDocument1-LabelInMyDocument1}| yields:\ref{MyDocument1-LabelInMyDocument1}\\
\verb|\pageref{MyDocument1-LabelInMyDocument1}| yields:\pageref{MyDocument1-LabelInMyDocument1}\\
\verb|\ref{MyDocument2-LabelInMyDocument2}| yields:\ref{MyDocument2-LabelInMyDocument2}\\
\verb|\pageref{MyDocument2-LabelInMyDocument2}| yields:\pageref{MyDocument2-LabelInMyDocument2}\\
\verb|\ref{LabelInMyDocument3}| yields:\ref{LabelInMyDocument3}\\
\verb|\pageref{LabelInMyDocument3}| yields:\pageref{LabelInMyDocument3}\\

\end{document}

相关内容