1

I am writing a document using KOMAscript's scrreprt class, and I am writing a custom macro (\xref) to format text used for cross-references.

This macro takes the label name as an argument: \xref{mylabel}

I want to generate a different text depending on whether the label refers to a chapter/section/subsection (numbered by default) or to a subsubsection/paragraph (unnumbered by default).

How can I check this? Any of the following two would do:

  1. Check if the label refers to a chapter/section/subsection (or the opposite: Check if the label refers to a subsubsection/paragraph)
  2. Check if the label refers to a numbered item
  • 2
    Package zref is a good friend, see for example my answer to this question here: tex.stackexchange.com/questions/312060/… – Christian Hupfer Feb 1 '17 at 12:38
  • 3
    You can use cleveref as well – Christian Hupfer Feb 1 '17 at 12:44
  • 1
    Well, what do you think scrreport makes use of in the final end? ;-) Using no extra packages, this you have to do redefinitions in the \label - \ref system. This requires some LaTeX skills. I don't see the point to reinvent the wheel. – Christian Hupfer Feb 1 '17 at 12:47
  • 1
    @Schweinebacke: But that's not expandable (as far as I can remember), which is necessary, to make it working in checks... and it is in an extra package ;-) – Christian Hupfer Feb 1 '17 at 12:52
  • 1
    @Grodiguez: LaTeX itself does not provide a type of element for labels. So you either need to use an additional package or you have to extend the label mechanism of LaTeX similar to such existing packages. I would recommend to use an existing package. – Schweinebacke Feb 1 '17 at 12:55
5

See the update for referring to unnumbered/numbered structure unit and checking at the end.

Without using any extra packages, only \renewcommand, \let, \pdfstrcmp etc. are used and writing a \@namedef to the .aux file.

It requires two runs (which are needed anyway, since we're dealing with labels!)

Use \extractlabeltype{labelname} and \checklabeltype with true/false branch.

It assumes that no other package is involving with \label and \ref, i.e. no hyperref or cleveref is supported.

\documentclass{book}


\makeatletter
\let\latex@@refstepcounter\refstepcounter
\let\latex@@label\label%


\renewcommand{\refstepcounter}[1]{%
  \gdef\lastrefsteppedcounter{#1}%
  \latex@@refstepcounter{#1}%
}

\renewcommand{\label}[1]{%
  \immediate\write\@auxout{\string\global\string\@namedef{label#1}{\lastrefsteppedcounter}}
   \latex@@label{#1}%
}

\newcommand{\extractlabeltype}[1]{%
  \@nameuse{label#1}%
}

\makeatother

\newcommand{\checklabeltype}[4]{%
\ifnum0=\pdfstrcmp{\extractlabeltype{#1}}{#2}
#3%
\else
#4%
\fi
}


\begin{document}



\chapter{Foo} \label{foo}


\section{Foosection}\label{foosection}

\checklabeltype{foosection}{section}{Yes, it is section}{No, it is something different}

\checklabeltype{foo}{section}{Yes, it is section}{No, it is something different}


\end{document}

enter image description here

Update with checking for unnumbered/numbered issues.

Please not that this deliberately depends on the assumption that the anchor name of a unnumbered structure unit has a * in it, so playing around with \theH... macros is no good idea ;-)

\documentclass{book}

\usepackage{xparse}
\usepackage[hyperref,counter]{zref}% Using the counter mechanism behind `nameref`
\usepackage{hyperref}


\makeatletter
\AtBeginDocument{%
  \let\latex@@label\label%

  \renewcommand{\label}[1]{%
    \zref@label{#1}%
    \latex@@label{#1}%
  }
  % Get the underlying counter type
  \newcommand{\extractlabelcounter}[1]{%
    \zref@ifrefundefined{#1}{%
      ???????}{%
      \zref@extract{#1}{counter}%
    }%
  }
  % Get the anchor name for hyperref or nameref -> has a `*` inside if it is unnumbered
  \newcommand{\extractlabelanchor}[1]{%
    \zref@ifrefundefined{#1}{%
      ???????}{%
      \zref@extract{#1}{anchor}%
    }%
  }
}

% Check if there's a `*` inside of the anchor name
\ExplSyntaxOn
\cs_new:Npn \checkifnumbered#1#2#3{%
  \tl_set:Nx \l_tmpa_tl {\extractlabelanchor{#1}}
  \tl_if_in:NnTF \l_tmpa_tl {*} {#2} {#3}
}
\ExplSyntaxOff

\makeatother


\newcommand{\checklabeltype}[4]{%
  \ifnum0=\pdfstrcmp{\extractlabelcounter{#1}}{#2}
  #3%
  \else
  #4%
  \fi
}

\begin{document}
\chapter{Foo} \label{foo}

\section*{An unnumbered section} \label{unnumbered}

\section{Foosection}\label{foosection}

\checklabeltype{foosection}{section}{Yes, it is section}{No, it is something different}

\checklabeltype{foo}{section}{Yes, it is section}{No, it is something different}

\begin{enumerate}
\item First \label{enumfirst}
\item Second \label{enumsecond}
\end{enumerate}

\checklabeltype{enumsecond}{enumi}{It is a numbered item and has the value \ref{enumsecond}}{}

In \nameref{unnumbered} we have an \checkifnumbered{unnumbered}{unnumbered}{numbered} \extractlabelcounter{unnumbered}


In \nameref{foo} we have an \checkifnumbered{foo}{unnumbered}{numbered} \extractlabelcounter{foo} whereas
 \nameref{foosection} is a \checkifnumbered{foosection}{unnumbered}{numbered} \extractlabelcounter{foosection}.


\end{document}

enter image description here

  • +1 for a solution that's compatible with the hyperref and cleveref packages. :-) – Mico Feb 1 '17 at 13:25
  • @Mico: Is it? I did not check. I doubt that cleveref's \label[...]{...} will like this ;-). – Christian Hupfer Feb 1 '17 at 13:27
  • @Grodriguez: It's a little bit more complicate with zref but more flexible, currently I am not sure that cleveref is the right package for your needs – Christian Hupfer Feb 1 '17 at 13:45
  • 1
    @Grodiguez: That's just because hyperref changes refstepcounter. \nameref is not expandable, by the way – Christian Hupfer Feb 1 '17 at 22:59
  • 1
    @ChristianHupfer Your updated solution works like a charm. This is just what I was looking for. – Grodriguez Feb 6 '17 at 11:50

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.