我正在尝试在两个文档之间创建引用。通常情况下,这样做效果很好,但我不明白为什么siunitx
在章节名称中使用会导致构建错误。
简单示例:
doc1.tex
\documentclass{book}
\usepackage{siunitx,xr-hyper,hyperref,lipsum}
\sisetup{detect-all=true}
\externaldocument{doc2}
\begin{document}
\chapter{Test \SI{1}{\GeV}}
\label{chap:test1}
\lipsum[1]
\ref{chap:test2}
\end{document}
doc2.tex
\documentclass{book}
\usepackage{siunitx,xr-hyper,hyperref,lipsum}
\externaldocument{doc1}
\begin{document}
\chapter{Test \SI{2}{\GeV}}
\label{chap:test2}
\lipsum[1]
\ref{chap:test1}
\end{document}
构建序列
$ pdflatex doc1.tex
...(no errors)
$ pdflatex doc2.tex
! Undefined control sequence.
<argument> Test \SI {1}{\GeV
}\relax
我把范围缩小到什么时候externaldocument
开放doc1.aux,最后一行出现错误:\newlabel{chap:test1}{{1}{1}{Test \SI {1}{\GeV }\relax }{chapter.1}{}}
正确。
有没有什么方法可以让它正确解析 aux 文件?
答案1
包xr-hyper
扩展了标签内容。更好的替代方案xr-hyper
是zref-xr
还可以导入和导出 LaTeX 标签:
\documentclass{book}
\usepackage{siunitx,hyperref,lipsum}
\usepackage{nameref,zref-xr}
\zxrsetup{toltxlabel}
\zexternaldocument*{doc1}
\begin{document}
\chapter{Test \SI{2}{\GeV}}
\label{chap:test2}
\lipsum[1]
\ref{chap:test1}, \nameref{chap:test1}
\end{document}
包nameref
应该在 之前加载\zexternaldocument
,因为它会改变内部引用格式。稍后在 中hyperref
加载。nameref
\begin{document}
答案2
添加
\let\GeV\relax
在调用之前对每个文档进行\externaldocument
并且它应该正常运行。
答案3
nameref
检索\GetTitleString
分区标题并将其存储在 中\@currentlabelname
。您可以覆盖此前使其\label
不包含来自siunitx
下面的宏\updatelabelname{<new name>}
可以实现这个功能:
\makeatletter
\newcommand*{\updatelabelname}[1]{% For correcting \@currentlabelname, if needed
\xdef\@currentlabelname{#1}}
\makeatother
在两个文件中都包含上述内容并使用
doc1.tex
\chapter{Test \texorpdfstring{\SI{1}{\GeV}}{1 GeV}}
\updatelabelname{Test 1 GeV}
doc2.tex
\chapter{Test \texorpdfstring{\SI{2}{\GeV}}{2 GeV}}
\updatelabelname{Test 2 GeV}
\texorpdfstring
还请注意,通常使用可以在 TeX 相关内容(如 ToC)和 PDF 内容(如书签)之间正确切换。