与 xr-hyper 交叉引用时未定义控制序列

与 xr-hyper 交叉引用时未定义控制序列

我正在尝试在两个文档之间创建引用。通常情况下,这样做效果很好,但我不明白为什么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-hyperzref-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 内容(如书签)之间正确切换。

相关内容