# How to find out what type of section a given \ref refers to

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
• Package zref is a good friend, see for example my answer to this question here: tex.stackexchange.com/questions/312060/… – user31729 Feb 1 '17 at 12:38
• You can use cleveref as well – user31729 Feb 1 '17 at 12:44
• 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. – user31729 Feb 1 '17 at 12:47
• @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 ;-) – user31729 Feb 1 '17 at 12:52
• @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

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}


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}


• +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 ;-). – user31729 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 – user31729 Feb 1 '17 at 13:45
• @Grodiguez: That's just because hyperref changes refstepcounter. \nameref is not expandable, by the way – user31729 Feb 1 '17 at 22:59
• @ChristianHupfer Your updated solution works like a charm. This is just what I was looking for. – Grodriguez Feb 6 '17 at 11:50