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/… – user31729 Feb 1 '17 at 12:38
  • 3
    You can use cleveref as well – user31729 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. – user31729 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 ;-) – user31729 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 ;-). – 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
  • 1
    @Grodiguez: That's just because hyperref changes refstepcounter. \nameref is not expandable, by the way – user31729 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 agree to our terms of service, privacy policy and cookie policy

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