摘要
交叉引用系統是LaTeX最強大的功能之一——可以在文檔的任意地方引用帶編號的結構,包括標題、圖形、表格、公式等,並且更重要的是可以自動更新引用編號。本文概述了交叉引用系統,並介紹一些相關的擴展宏包。
1. 簡介
LaTeX 實現了 \label和\ref宏,進而可以引用同一文檔內的絕大部分帶編號對象。首先用\label賦予唯一標識符給某個帶編號的對象,然后就可以使用\ref宏進行引用。此外,另一個不那么常用的命令是\pageref,它可以輸出被引用對象所在的頁碼數。
在下面的例子中,假設文檔的第一節標題為“Introduction”,在該節添加了標記符sec:intro,之后就可以在接下來的章節中使用該標記符來指代之前的節:\ref{sec:intro}就會輸出數字1。
\section{Introduction}\label{sec:intro}
% Content
\section{Methods}
In section \ref{sec:intro} on page
\pageref{sec:intro} we introduced ...
2. 指定標簽或標記符
引用的標記符並沒有什么格式上的限制。不過,通用的做法是使用前綴+冒號作為標記符的開頭。添加前綴可以幫助作者識別被引用對象的類型。例如,引用圖形的標記符可以是\label{fig:schema}這樣的形式。對於一些最常用的引用對象,下表給出了相應的前綴名建議。
| 對象 | 前綴 | 對象 | 前綴 |
|---|---|---|---|
| Chapter | ch | Figure | fig |
| Section | sec | Table | tab |
| Subsection | ssec | List item | itm |
| Appendix | app | Equation | eqn |
當然,使用前綴是個好習慣,不過這也僅僅是建議——作者完全可以使用另一套前綴或者根本不使用。
3. 標簽的位置
理想情況下,應該在被引用的計數對象之后立即放置\label標記。而對於圖形或表格這樣的浮動環境,應在\caption宏內或之后放置\label,這是因為圖形或表格的編號是由\caption生成的。如果在編號對象之前使用\label基本上都會導致引用錯誤。當然,在編號對象之后太久才使用\label也可能會有問題。
4. 引用的生成和更新
一般來說需要兩次運行排版命令才能生成引用編號。背后的原理是這樣的,第一次運行排版命令時,系統會收集所有標記符信息,並寫入一個輔助文件內;而再次運行排版命令時,系統會讀取該輔助文件並進而更新引用。只要系統不能正確生成引用,那么在輸出文檔的相應位置就會生成雙問號??標記。如果再次排版后還不能更新正確的引用,可以看一下log日志文件確定問題。下一節將介紹引用相關的警告信息。
5. 引用相關的警告信息
log日志文件中出現與引用相關的警告並不少見。如果標識符的定義有問題,一般會出現兩種警告:1. 未定義的引用(undefined references)2. 重復定義的標簽(multiply-defined labels)
第一種情況是由於引用的標識符沒有定義,而第二種情況是由於多次定義了同一標識符。例如,如果作者復制一些代碼片段(比如圖形環境)而忘記重命名其中的標識符,那么就會出現重復定義標簽的問題。
6. 擴展引用功能的宏包
很多宏包都擴展了LaTeX的交叉引用系統。這里簡要介紹以下幾個宏包:varioref, cleveref, hyperref, xr/xr-hyper。選擇這些宏包的原因是每個宏包都在獨特的方面擴展了原有的功能。大體上來說,這些宏包並沒有重新定義標准引用命令的功能,而是定義了新命令。因此,標准的\label, \ref和\pageref功能並不會受到影響。
6.1 varioref宏包
varioref宏包將基礎的引用命令擴展為略微更加復雜的形式。其中,\vref命令合並了\ref和\pageref的功能,會同時輸出被引用對象的編號和所在的頁碼數。如果被引用對象位於同一頁,那么會省略頁碼數。而\vpageref則增加了\pageref的功能:如果被引用對象位於同一頁則輸出“on this page”,否則輸出所在頁碼數。最后,該宏包還提供了\vrefrange和\vpagerefrange命令,用於多重引用時輸出編號也頁碼范圍。
6.2 cleveref宏包
很多情況下作者都會在文本中提及所引用對象的類型。例如,某個圖形可以引用為“This is shown in figure 1”。而\ref宏只會輸出所引用對象的編號,因此這就是cleveref宏包的作用。該宏包會自動識別引用對象的類型,並打印出對應的引用。為此,該宏包提供了\cref命令。類似於varioref宏包,本宏包也實現了輸出引用對象所在頁碼的宏\cpageref和頁碼范圍的宏\cpagerefrange。
6.3 hyperref宏包
hyperref宏包中涉及交叉引用的主要功能是給引用加上鏈接:點擊該引用會轉到被引用對象所在的頁面。只要在導言區導入該宏包即可實現相應功能。同時,該宏包還定義了\autoref宏,其功能類似於cleveref宏包中的\cref命令,即同時輸出引用編號和引用類型。此外,該宏包實現了大量與交叉引用無關的其它功能,相關討論已經超出了本文的主題范圍。盡管如此,這里仍然推薦瀏覽一下該宏包的文檔以了解該宏包的更多信息。
6.4 xr/xr-hyper宏包
xr宏包(eXternal References)可以引用其它文檔中的對象。這在科技論文中特別有用,因為經常要在正文之外提供補充材料。使用該宏包就可以在正文中引用補充材料中的圖形和表格。要實現此功能,必須在正文的導言區內使用\externaldocument{filename} 來指定外部文檔。如果外部的tex文件位於不同文件夾下,那么也要指定相應的路徑。然后就可以在正文中引用外部文檔中的標識符了。另外要注意的是外部文檔每次修改引用標簽后都要編譯一下,這樣正文中才能生成正確的編號。
\documentclass{article}
\usepackage{xr}
\externaldocument{supplementary-materials}
\begin{document}
See supplementary figure \ref{fig:abc}.
\end{document}
對於這樣指向外部文檔的引用,如果還想要創建超鏈接,那么使用xr-hyper宏包代替xr。
6.5 宏包載入順序
由於這些宏包都會影響引用的行為,因此,載入多個宏包可能造成沖突。所以,宏包載入時需要按照正確的順序,即:(1) xr/xr-hyper, (2) varioref, (3) hyperref, 最后是 (4) cleveref。
6.6 showlabels 宏包
最后要提一下showlabels宏包,其功能是在輸出的PDF文檔的頁邊處顯示標識符。因此,該宏包特別適用於在帶有大量標簽的長文檔中追蹤標識符的場合。
參考文獻
cleveref: Intelligent cross-referencing.hyperref: Extensive support for hypertext in LATEX.showlabels: Show label commands in the margin.varioref:Intelligent page references.xr: References to other LATEX documents.
說明:
- 本文翻譯自Thomas Thurnherr, An introduction to the LATEX cross-referencing system, TUGboat, Volume 38 (2017), No. 1
- 遵循署名-非商業性使用-相同方式共享 4.0 國際(CC BY-SA 4.0)協議發布。因此,可以自由地對博客中內容進行分享、創作演繹直至商業性的使用,但必須在文章末尾或參考文獻處注明文章的出處(文章鏈接)。完整的協議可以參看這里。
