> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/zh-cn/zhi-shi-ku/033-cross-referencing-with-the-xr-package-in-overleaf.md).

# 在 Overleaf 中使用 xr 宏包进行交叉引用

## 概述

该 [`xr` 宏包](https://ctan.org/pkg/xr?lang=en) 让你为外部 LaTeX 文档中包含的公式、图、表等创建交叉引用，前提是这些文档是 *独立的。* 一个独立的 LaTeX 文档之所以可以编译，是因为它包含 `\documentclass{...}` 语句以及 `\begin{document}`...`\end{document}` 构造。

### 用法摘要

1. 写入 `\usepackage{xr}` 在需要对外部 LaTeX 文件中包含的内容进行交叉引用的 LaTeX 文件导言区中。
2. 使用 `xr` 包命令 `\externaldocument{filename}` 用来指定你想交叉引用其内容的外部文档。

该 `xr` 该宏包通过使用包含在……中的交叉引用标签来工作 `.aux` 这些文件是在外部 LaTeX 文档编译时生成的。

### 交叉引用的工作原理（简要摘要）

要在 LaTeX 文档中对某个项目进行交叉引用，你需要：

1. 给它一个唯一标识符， `some_string`，使用 `\label` 命令设置为特定值：

```latex
\label{some_string}
```

3. 在你想引用该元素的位置，需要写

```latex
\ref{some_string}
```

简而言之，LaTeX 通过将数据写入一个名为……的文件来管理交叉引用 `filename.aux` 其中 `filename` 是主 `.tex` 正在编译的文件名。

为了使该过程生效，LaTeX 文档必须至少编译两次：第一次编译 *生成* 引用数据——将其写入 `filename.aux`。在第二次编译时，LaTeX *读取* `filename.aux` 以解析这些引用，并提供数据来替换……的实例 `\ref{some_string}`.

* 有关交叉引用的更多细节，请参见 Overleaf 文章 [交叉引用章节、公式和浮动体](/latex/zh-cn/wen-dang-jie-gou/03-cross-referencing-sections-equations-and-floats.md).

## 不需要 xr 宏包的项目

大型 LaTeX 项目，例如书籍或长篇报告，通常会拆分成一系列较小的 `.tex` 文件，每章一个，每一章的 `.tex` 文件通过以下方式加入主 LaTeX 文档： `\input` 或 `\include`。通常，这些章节并不是独立的：你不能单独编译各章，因为它们不包含 `\documentclass{...}` 语句或 `\begin{document}...\end{document}` 构造。这些章节是用于 *插入* 到一个“容器”文档中，而该文档 *可以* 被编译。在这种情况下，对文档元素的交叉引用——在任何单独的章节文件中——可以正常进行：你不需要使用 `xr` 宏包。

要查看大型项目示例，你可以  [在 Overleaf 中打开此示例。](https://www.overleaf.com/project/new/template/20618?id=70769185\&templateName=Managing+a+large+project+on+Overleaf\&latexEngine=pdflatex\&texImage=texlive-full%3A2020.1\&mainFile=)

## 需要 xr 宏包的项目示例

假设你有一组独立的 LaTeX 文档，例如由 N 篇文章组成的集合： `article1.tex`, `article2.tex` ... `articleN.tex`。这些文章都可以单独编译，而且它们很可能是使用各种文档类、宏包等编写的。

现在设想你想用 LaTeX 来撰写这些文章的概述或摘要——我们把我们的文件称为 `summary.tex`。我们的摘要需要引用这些独立的、N 篇文章中的章节、图、表、公式等。我们该如何做到这一点？

该 `xr` 该宏包可以让你做到这一点：它使 `summary.tex` 能够使用任何独立 `article*.tex` .bib 文件。

### 关于 .aux 文件的说明

* 注意，这里我们使用星号（`*`）作为 1 到 N 中任意数字的占位符。

编译任一独立文件 `article1.tex`, `article2.tex` ... `articleN.tex` 会使 LaTeX 生成相应的 `article*.aux` (\*\*`aux`\*\*辅助）文件，其中除其他内容外，还包含生成交叉引用所需的标签数据。

如果其中任何 `article*.tex` 文件被编辑——例如，更改、添加或删除标签（`\label{...}`）——相应的 `article*.tex` 文件必须重新编译，以更新相关的 `article*.aux` 文件。

检测……中的更改 `article*.tex`，并随后重新编译它们，可以在 Overleaf 中通过使用合适的……来自动化 `latexmkrc` 文件。

## 如何在 Overleaf 上使用 xr

我们将使用多文章示例的简化版本；具体来说，我们将展示如何通过一个……来自动化编译过程 `latexmkrc` 文件 [由 John Collins 提供给 Overleaf 的](#code-for-latexmkrc) ([维护者 `latexmk`](https://ctan.org/pkg/latexmk?lang=en)).

### 我们示例中使用的文件

我们的示例使用以下文件：

* `**summary.tex**`：这是我们的概述文档。我们需要它来引用……中包含的内容 `article1.tex`，例如图和章节。
  * `summary.tex` 加载 `xr` 宏包，并使用 `\externaldocument{article1}` 用来指定来自……的引用数据 `article1.aux` 应被使用。
* `**article1.tex**`：一篇包含内部交叉引用的独立文章。编译 `article1.tex` 会生成包含在文件中的交叉引用数据 `article1.aux`.
  * 像……这样的外部文件 `article1.tex` 可能是由他人编写的——供你“按原样”使用，也就是不做任何改动。
* `**latexmkrc**`：包含用于自动重新编译……的代码（Perl） `article1.tex` 由于对其所做的任何更改——以创建更新的 `article1.aux` 文件。
  * 我们的 `latexmkrc` 文件是 [由 John Collins 提供给 Overleaf 的](#code-for-latexmkrc) ([维护者 `latexmk`](https://ctan.org/pkg/latexmk?lang=en)).

### 关于 \externaldocument 命令

该 `xr` 宏包提供了`\externaldocument` 命令，其一般形式为

```latex
\externaldocument[prefix]{external_file}
```

* **`前缀` （可选）：** 这个可选参数允许你定义一个前缀，该前缀会添加到从外部文档导入的所有标签上。如果多个文档中使用了相同的标签名，这有助于避免冲突。
* **`external_file` （必需）：** 这个必需参数指定外部 LaTeX 文档的名称（不含 `.tex` 扩展名），你要从中导入引用。该 `xr` 宏包将查找 `.aux` 对应于……的文件 `external_file` （例如， `external_file.aux`）以检索这些标签。

例如，如果我们的主 `.tex` 文件 `summary.tex` 以及外部文件 `article1.tex` 都包含标签 `\label{eq:1}` 那么就会发生标签名冲突。可以通过写入以下内容来避免该冲突：

```latex
\externaldocument[art1-]{article1}
```

在这种情况下，编译 `article1.tex` 所创建的所有标签都会加上前缀 `art1-`。现在你可以访问 `\label{eq:1}`，其中包含于 `article1.tex`，只需写 `\ref{art1-eq:1}` 在 `summary.tex`.

### 项目文件

#### article1.tex

可使用代码列表下方的链接在 Overleaf 中打开以下代码。

```latex
\documentclass{article}
\title{这是 \texttt{article1.tex}}
\begin{document}
\section{引言}
\label{introduction}

这是一份独立的 \LaTeX{} 文档，包含
我们想在 \texttt{summary.tex} 中使用的引用。

\subsection{Math references}
\label{mathrefs}
如 \ref{introduction} 节所述，
不同的元素可以在……中被引用
一份文档中。

\subsection{幂级数}
\label{powers}

\begin{equation}
\label{eq:1}
\sum_{i=0}^{\infty} a_i x^i
\end{equation}

公式 \ref{eq:1} 是一个典型的幂级数。
\end{document}
```

&#x20;[打开 `article1.tex` 在 Overleaf 中](https://www.overleaf.com/docs?engine=%5B%5B%3ATemplate%3AEngine%5D%5D}\&snip_name\[]=readme.txt\&snip\[]=A+project+created+from+the+Overleaf+wiki\&snip_name\[]=article1.tex\&main_document=article1.tex\&snip\[]=%5Cdocumentclass%7Barticle%7D%0A%5Ctitle%7BThis+is+%5Ctexttt%7Barticle1.tex%7D%7D%0A%5Cbegin%7Bdocument%7D%0A%5Csection%7BIntroduction%7D%0A%5Clabel%7Bintroduction%7D%0A%0AThis+is+a+standalone+%5CLaTeX%7B%7D+document+with%0Areferences+we+want+to+use+in+%5Ctexttt%7Bsummary.tex%7D.%0A%0A%5Csubsection%7BMath+references%7D%0A%5Clabel%7Bmathrefs%7D%0AAs+mentioned+in+section+%5Cref%7Bintroduction%7D%2C+%0Adifferent+elements+can+be+referenced+within%0Aa+document.%0A%0A%5Csubsection%7BPowers+series%7D%0A%5Clabel%7Bpowers%7D%0A%0A%5Cbegin%7Bequation%7D%0A%5Clabel%7Beq%3A1%7D%0A%5Csum_%7Bi%3D0%7D%5E%7B%5Cinfty%7D+a_i+x%5Ei%0A%5Cend%7Bequation%7D%0A%0AEquation+%5Cref%7Beq%3A1%7D+is+a+typical+power+series.%0A%5Cend%7Bdocument)

编译 `article1.tex` 会产生以下输出：

![在 Overleaf 上编译 article1.tex 文件生成的输出](/files/81252137ff3a28a36f8ce5d1beedd70b80ee633c)

#### summary.tex

这是我们的初始 `summary.tex` 文件 *在……之前* 我们已指定要引用哪个外部文档。为简单起见， `summary.tex` 不包含任何 `\label` 命令，因为没有内部交叉引用。所有 `\ref` 命令都引用由……生成的标签 `\label` 包含在……中的命令 `article1.tex`.

```latex
\documentclass{article}
\usepackage{xr}
\title{这是 \texttt{summary.tex}}
\begin{document}
在 \texttt{article1.tex} 文件中，导言是第 \ref{introduction} 节。该文件中有两个小节：\ref{mathrefs} 和 \ref{powers}。在 \ref{powers} 小节中，公式 \ref{eq:1} 展示了一个幂级数。
\end{document}
```

&#x20;[在 Overleaf 中打开此 *不完整* `summary.tex` 在 Overleaf 中](https://www.overleaf.com/docs?engine=%5B%5B%3ATemplate%3AEngine%5D%5D}\&snip_name\[]=readme.txt\&snip\[]=A+project+created+from+the+Overleaf+wiki\&snip_name\[]=summary.tex\&main_document=summary.tex\&snip\[]=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bxr%7D%0A%5Ctitle%7BThis+is+%5Ctexttt%7Bsummary.tex%7D%7D%0A%5Cbegin%7Bdocument%7D%0AIn+the+file+%5Ctexttt%7Barticle1.tex%7D%2C+the+introduction+is+section+%5Cref%7Bintroduction%7D.++In+that+file%2C+there+are+two+subsections%3A+%5Cref%7Bmathrefs%7D+and+%5Cref%7Bpowers%7D.+In+subsection+%5Cref%7Bpowers%7D%2C+equation+%5Cref%7Beq%3A1%7D+demonstrates+a+power+series.%0A%5Cend%7Bdocument%7D)

如果我们编译这个版本的 `summary.tex` 它将尝试从……读取引用数据 `summary.aux` 但所需数据包含在外部文件中 `article1.aux` 目前还无法访问。

编译这个不完整的 `summary.tex` 文件会产生以下输出，其中双问号表示未定义的引用：

![显示缺失引用报告的图片](/files/03883f30721e48066e420b1a92a83eccebf17701)

### 指定外部文档

下一步是指定 `article1` 作为我们要引用其标签的外部文档名称。将以下行添加到……的导言区中 `summary.tex`:

```latex
\externaldocument{article1}
```

这里， `article1` 可以替换为任何你想访问其标签的文件——你可以使用多个 `\externaldocument` 命令来访问额外的外部文件。

### 创建 latexmkrc 文件

下一步是创建一个 `latexmkrc` 如下所示的文件：

* 在项目编辑器窗口中，选择 **新文件** 项目窗口左上角的图标。
* 选择 **新文件** 在……中 **添加文件** 弹出对话框，并将文件命名为 `latexmkrc`——注意没有文件扩展名：

![在 Overleaf 中创建 latexmkrc 文件](/files/63b7fb954e5d7a8c007b4acbab907205032061d0)

* 确保 `latexmkrc` 文件创建并保存于项目文件区域的顶部（根）级别。也就是说，不要放在文件树中的任何文件夹内。
* 将以下代码复制并粘贴到你的 `latexmkrc` 文件。

#### latexmkrc 代码

Overleaf 感谢 John Collins， [维护者 `latexmk`](https://ctan.org/pkg/latexmk?lang=en)，感谢他联系我们提供以下 `latexmkrc` 文件，我们很高兴全文发布——包括那些极其有用的行内注释。

```perl
# 这展示了如何将 xr 宏包与 latexmk 一起使用。
# John Collins 2023-03-29
#
# xr 宏包（“外部引用系统”）由文档使用
# 用于在其他外部的……中引用章节、公式等
# 文档。
# 本文件中的定义使 latexmk 能够将 latexmk 应用于
# 当外部文档的 .tex 文件发生变化时自动更新它，
# 这样主文档中的引用就能保持最新。

# 注：
#    1. 此版本被定义为将……编译生成的文件放入
#       外部文档放入一个指定的子目录，以分隔
#       可能大量生成的文件与主文档
#       目录。
#    2. 但要像这里这样使用 latexmk 的自定义依赖机制，
#       子文档编译生成的 aux 文件必须生成在
#       与对应源 .tex 文件相同的目录中。因此，
#       会复制 .aux 文件。
#    3. 假定外部文档将由
#       pdflatex 编译。当然，可以通过更改所调用 latexmk 的 ‘-pdf’
#       选项为所需的其他选项来更改这一点。
#    4. 理想的实现还应确保对……的重新编译
#       每当其任何其他源
#       文件发生变化时也会进行。但当前版本尚未这样做，并且
#       这可能需要使用 latexmk 的内部变量，
#       或对 latexmk 进行额外增强。
#    5. 代码使用了由
#       latexmk 从 Perl 包 File::Copy 和 File::Basename 加载的子程序 copy 和 fileparse。
#    6. 它还使用了 latexmk 一些尚未文档化的特性：一个数组
#       变量 @file_not_found，以及子程序 popd、pushd 和
#       rdb_add_generated。

#--------------------
# 外部文档编译的可配置选项

# 外部文档编译生成输出文件的子目录：
$sub_doc_output = 'output-subdoc';

# 提供给 latexmk 用于编译外部文档的选项：
@sub_doc_options = ();

push @sub_doc_options, '-pdf'; # 使用 pdflatex 编译外部文档。
# 如有需要，可将 '-pdf' 替换为 '-pdfdvi'、'pdfxe' 或 'pdflua'。

#--------------------

# 将 xr 关于缺失文件的日志消息模式添加到 latexmk 的
# 列表中。Latexmk 的变量 @file_not_found 尚未文档化。
# 对于 latexmk 4.80 或更高版本，这一行不是必需的。
push @file_not_found, '^No file\\s*(.+)\s*$';

add_cus_dep( 'tex', 'aux', 0, 'makeexternaldocument' );
sub makeexternaldocument {
    if ( $root_filename ne $_[0] )  {
        my ($base_name, $path) = fileparse( $_[0] );
        pushd $path;
        my $return = system "latexmk",
                            @sub_doc_options,
                            "-aux-directory=$sub_doc_output",
                            "-output-directory=$sub_doc_output",
                            $base_name;
        if ( ($sub_doc_output ne '') && ($sub_doc_output ne '.') ) {
               # 在这种情况下，由 pdflatex 生成的 .aux 文件不在同一
               # 目录中。
               # 因此：
               # 1. 实际生成的 aux 文件必须按此
               #    规则列出，以便 latexmk 正确处理依赖关系。
               #    （需要克服的问题：如果 $sub_dir_output 与主文档的 $aux_dir
               #    相同，那么 xr 可能读取
               #    aux_dir 中的 .aux 文件，而不是 latexmk 根据自定义依赖假定会生成的那个文件，
               #    该文件位于 .tex 源
               #    文件所在的同一目录中。
               #    使用尚未文档化的 latexmk 子程序 rdb_add_generated
               #    来实现这一点：
               # 2. .aux 文件的副本必须与 .tex 文件位于同一目录中
               #    以满足 latexmk 对自定义依赖的定义。
             rdb_add_generated( "$sub_doc_output/$base_name.aux" );
             copy "$sub_doc_output/$base_name.aux", ".";
        }
        popd;
        return $return;
   }
}
```

### 打开一个演示 xr 的 Overleaf 项目

现在可以使用上方和下方文件列表提供的链接在 Overleaf 中打开以下三文件项目。请注意， `latexmkrc` 该文件包含 John Collins 提供的代码，但为简洁起见，大部分注释已被删除。

&#x20;[在 Overleaf 中打开此三文件示例。](/latex/zh-cn/zhi-shi-ku/033-cross-referencing-with-the-xr-package-in-overleaf.md)

**summary.tex**

这是我们的摘要文件。我们希望在此文件中使用外部文件中创建的交叉引用。这里，我们希望使用由 `article1.tex`.

```latex
\documentclass[12pt]{article}
\usepackage{xr}

\title{在 Overleaf 上使用 xr 宏包}
% 将所有外部文档放在这里！
\externaldocument{article1}

\begin{document}

在 \texttt{article1.tex} 文件中，导言是第 \ref{introduction} 节。该文件中有两个小节：\ref{mathrefs} 和 \ref{powers}。在 \ref{powers} 小节中，公式 \ref{eq:1} 展示了一个幂级数。

\end{document}
```

**article1.tex**

该文件是我们的文章之一。请注意它包含各种 `\label` 用于创建标签的命令，这些标签得益于 `xr` 宏包，我们可以在文件中使用 `summary.tex`.

```latex
\documentclass{article}
\title{这是 \texttt{article1.tex}}
\begin{document}
\section{引言}
\label{introduction}

这是一份独立的 \LaTeX{} 文档，包含
我们想在 \texttt{summary.tex} 中使用的引用。

\subsection{Math references}
\label{mathrefs}
如 \ref{introduction} 节所述，
不同的元素可以在……中被引用
一份文档中。

\subsection{幂级数}
\label{powers}

\begin{equation}
\label{eq:1}
\sum_{i=0}^{\infty} a_i x^i
\end{equation}

公式 \ref{eq:1} 是一个典型的幂级数。
\end{document}
```

**latexmkrc**

这 `latexmkrc` 文件包含用于确保外部文件被编译的代码。

```latex
$sub_doc_output = 'output-subdoc';

@sub_doc_options = ();

push @sub_doc_options, '-pdf'; # 使用 pdflatex 编译外部文档。
# 如有需要，可将 '-pdf' 替换为 '-pdfdvi'、'pdfxe' 或 'pdflua'。

push @file_not_found, '^No file\\s*(.+)\s*$';

add_cus_dep( 'tex', 'aux', 0, 'makeexternaldocument' );
sub makeexternaldocument {
    if ( $root_filename ne $_[0] )  {
        my ($base_name, $path) = fileparse( $_[0] );
        pushd $path;
        my $return = system "latexmk",
                            @sub_doc_options,
                            "-aux-directory=$sub_doc_output",
                            "-output-directory=$sub_doc_output",
                            $base_name;
        if ( ($sub_doc_output ne '') && ($sub_doc_output ne '.') ) {

             rdb_add_generated( "$sub_doc_output/$base_name.aux" );
             copy "$sub_doc_output/$base_name.aux", ".";
        }
        popd;
        return $return;
   }
}
```

&#x20;[在 Overleaf 中打开此三文件示例。](/latex/zh-cn/zhi-shi-ku/033-cross-referencing-with-the-xr-package-in-overleaf.md)

下图是排版……输出的带注释版本 `summary.tex`，展示了交叉引用以及来自外部文件的对应标签 `article1.tex`.

![显示从外部文件导入的引用](/files/28377d8b8484b2c0a2a35ea0cb1ea4a6ae32ec91)

* 有关交叉引用的更多细节，请参见 Overleaf 文章 [交叉引用章节、公式和浮动体](/latex/zh-cn/wen-dang-jie-gou/03-cross-referencing-sections-equations-and-floats.md).

## 关于语法错误的说明

对于主项目文件，你可以使用 Overleaf 的 [立即停止于第一个错误编译模式](/latex/zh-cn/zhi-shi-ku/149-using-the-stop-on-first-error-compilation-mode.md) 以确保一旦检测到第一个错误，编译就立即终止。这有助于隔离并识别代码中的错误，而不是让错误连锁出现，从而使问题更难发现和调试。

该 *external* 文档通过……自动编译 `latexmkrc` 文件；因此，其中的任何 LaTeX 语法错误都不会显示在 Overleaf 界面中——除非你也在 Overleaf 中重新编译它们。外部文件中的错误可能会导致交叉引用无法在排版后的 PDF 文件中正确显示，因此我们强烈建议一旦出现此类错误就立即检查并更正。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/zh-cn/zhi-shi-ku/033-cross-referencing-with-the-xr-package-in-overleaf.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
