Update 2017/03/05 at the end
Update 2017/06/07: Similar question https://tex.stackexchange.com/a/373769/31729
Determining the parent counter of a counter is easy, if there is only one parent counter, so this is a unique mapping then.
I stored all counters being defined at the begin of the document in a sequence and 'cracked' the \cl@X
list (X
being a driver counter name, such as, say, chapter
), storing their content into a property list which contains the parent counter.
The \getparentcounter
macro can be used to retrieve the value.
Now the zref
package stores the properties childcountervalue
, parentcountervalue
and parentcountername
in order to retrieve them later with \zref@extract
.
The anchor is stored as well, just in case we're using hyperref
.
The macros \parentcref
and \parentCref
will output the parent counter and the child counter with the first character in lower case (which is the counter name, actually) and the first character in upper case, i.e. section → Section
etc.
The code assumes that the counters are using numbers only, i.e. \arabic{foo}
. I'll try to remove this limitation.
\documentclass{book}
\usepackage{etoolbox}
\usepackage{lipsum}
\usepackage{hyperref}
\usepackage[user,counter,hyperref]{zref}
\usepackage{cleveref}
\makeatletter
\AtEndPreamble{
\newif\if@hyperrefloaded
\@ifpackageloaded{hyperref}{%
\@hyperrefloadedtrue
}{
\@hyperrefloadedfalse
}
}
\makeatother
\usepackage{letltxmacro}
\usepackage{xparse}
\makeatletter
\ExplSyntaxOn
\prop_new:N \g_latex_parentcounters_prop
\seq_new:N \g_latex_counters_seq
\cs_generate_variant:Nn \seq_gset_from_clist:Nn {Nx,cx}
\cs_generate_variant:Nn \prop_item:Nn {Nx,cx,No}
\cs_generate_variant:Nn \str_head:n {x,o,V}
\cs_generate_variant:Nn \str_tail:n {x,o,V}
\cs_generate_variant:Nn \str_uppercase:n {x,o,V}
\cs_generate_variant:Nn \str_set:Nn {Nx,No}
% Store all reset lists and make a property list for each counter and its possible parent counter
\cs_new_nopar:Npn \GetAllResetLists {%
\def\@elt##1{%
\seq_gput_right:Nn \g_latex_counters_seq {##1}%
\seq_new:c { g_latex_cntr_##1_seq }
}
\cl@@ckpt%
\seq_map_inline:Nn \g_latex_counters_seq {%
\def\@elt####1{####1,}
\seq_gset_from_clist:cx { g_latex_cntr_##1_seq } { \use:c{cl@##1} }
}
% Now fill the parent counter lists
\seq_map_inline:Nn \g_latex_counters_seq {%
\seq_map_inline:cn { g_latex_cntr_##1_seq }{ %
\prop_gput:Nnn \g_latex_parentcounters_prop {####1} {##1}
}
}
}
% Gives the parent counter of a specific counter (or nothing)
\cs_new:Npn \getparentcounter #1{%
\prop_item:No \g_latex_parentcounters_prop {#1}
}
% Make the first character of a word upper case
\newcommand{\FirstUpcase}[1]{%
\str_set:Nx \l_tmpa_str {#1}%
\str_uppercase:x {\str_head:N \l_tmpa_str}\str_tail:V {\l_tmpa_str}%
}
\ExplSyntaxOff
\GetAllResetLists
\def\LastRefSteppedCounter{}
% Define new properties
\zref@newprop{childcountervalue}{\arabic{\LastRefSteppedCounter}}% This is the naked value
\zref@newprop{parentcountervalue}{\csname the\getparentcounter{\LastRefSteppedCounter}\endcsname}
\zref@newprop{parentcountername}{\getparentcounter{\LastRefSteppedCounter}}
% Add the new properties to the main property list stored with \zlabel
\zref@addprops{main}{childcountervalue,parentcountervalue,parentcountername}
\AtBeginDocument{%
\LetLtxMacro\latex@@label\label
\let\latex@@refstepcounterorig\refstepcounter
\RenewDocumentCommand{\refstepcounter}{m}{%
\global\xdef\LastRefSteppedCounter{#1}%
\latex@@refstepcounterorig{#1}%
}
%Make the ordinary label and a \zlabel
\RenewDocumentCommand{\label}{om}{%
\IfValueTF{#1}{%
\latex@@label[1]{#2}%
}{%
\latex@@label{#2}%
}%
\zlabel{#2}%
}%
}
% Command for uppercase output
\NewDocumentCommand{\parentCref}{m}{%
\zref@ifrefundefined{#1}{%
\Cref{#1}%
}{%
\edef\@tmpb@{\zref@extract{#1}{parentcountervalue}}%
\edef\@tmpa@{\csname the\zref@extract{#1}{parentcountername}\endcsname}%
\ifx\@tmpb@\@tmpa@
\Cref{#1}%
\else
\if@hyperrefloaded
\FirstUpcase{\zref@extract{#1}{counter}} \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{childcountervalue}} of \FirstUpcase{\zref@extract{#1}{parentcountername}} \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{parentcountervalue}}%
\else
\FirstUpcase{\zref@extract{#1}{counter}} \zref@extract{#1}{childcountervalue} of \FirstUpcase{\zref@extract{#1}{parentcountername}} \zref@extract{#1}{parentcountervalue}%
\fi
\fi
}%
}
% Command for lowercase output
\NewDocumentCommand{\parentcref}{m}{%
\zref@ifrefundefined{#1}{%
\cref{#1}%
}{%
\edef\@tmpb@{\zref@extract{#1}{parentcountervalue}}%
\edef\@tmpa@{\csname the\zref@extract{#1}{parentcountername}\endcsname}%
\ifx\@tmpb@\@tmpa@
\Cref{#1}%
\else
\if@hyperrefloaded
\zref@extract{#1}{counter} \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{childcountervalue}} of \zref@extract{#1}{parentcountername} \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{parentcountervalue}}%
\else
\zref@extract{#1}{counter} \zref@extract{#1}{childcountervalue} of \zref@extract{#1}{parentcountername} \zref@extract{#1}{parentcountervalue}%
\fi
\fi
}%
}
\makeatother
\begin{document}
\chapter{Chapter One}
Please look at \parentCref{othersection} or at \parentCref{foosubsection} or at \parentcref{foosubsection}
\section{Section One.One}
\label{mysection}
\lipsum
\section{Section One.Two}
\subsection{A subsection} \label{foosubsection}
Please ignore \parentCref{mysection}.
\chapter{Chapter Two}
\section{Section Two.One}
As you may have noticed, \parentCref{mysection} is useless.
\chapter{Chapter Three}
\section{Section Three.One}
\section{Section Three.Two}\label{othersection}
\end{document}

See Renumbering chapter after part, include part number as suffix in cross-reference to chapter number for a similar question, but that's not a duplicate!
Update 2017/03/06 Some features of this answer has been added to the xassoccnt
v1.3 package (Download from xassoccnt until it is available on CTAN, TeXLive (since 2017/03/06) and MikTeX) The solution is much shorter now:
\documentclass{book}
\usepackage{lipsum}
\usepackage{xassoccnt}
\usepackage{xpatch}
\usepackage{hyperref}
\usepackage[user,counter,hyperref]{zref}
\usepackage{cleveref}
\makeatletter
\AtEndPreamble{
\newif\if@hyperrefloaded
\@ifpackageloaded{hyperref}{%
\@hyperrefloadedtrue
}{
\@hyperrefloadedfalse
}
}
\makeatother
\usepackage{xparse}
\makeatletter
\ExplSyntaxOn
\prop_new:N \g_latex_parentcounters_prop
\seq_new:N \g_latex_counters_seq
\cs_generate_variant:Nn \str_head:n {x,o,V}
\cs_generate_variant:Nn \str_tail:n {x,o,V}
\cs_generate_variant:Nn \str_uppercase:n {x,o,V}
\cs_generate_variant:Nn \str_set:Nn {Nx,No}
% Store all reset lists and make a property list for each counter and its possible parent counter
% Make the first character of a word upper case
\newcommand{\FirstUpcase}[1]{%
\str_set:Nx \l_tmpa_str {#1}%
\str_uppercase:x {\str_head:N \l_tmpa_str}\str_tail:V {\l_tmpa_str}%
}
\ExplSyntaxOff
% Define new properties
\zref@newprop{childcountervalue}{\arabic{\LastRefSteppedCounter}}% This is the naked value
\zref@newprop{parentcountervalue}{\csname the\GetParentCounter{\LastRefSteppedCounter}\endcsname}
\zref@newprop{parentcountername}{\GetParentCounter{\LastRefSteppedCounter}}
% Add the new properties to the main property list stored with \zlabel
\zref@addprops{main}{childcountervalue,parentcountervalue,parentcountername}
% Command for uppercase output
\NewDocumentCommand{\parentCref}{m}{%
\zref@ifrefundefined{#1}{%
\Cref{#1}%
}{%
\edef\@tmpb@{\zref@extract{#1}{parentcountervalue}}%
\edef\@tmpa@{\csname the\zref@extract{#1}{parentcountername}\endcsname}%
\ifx\@tmpb@\@tmpa@
\Cref{#1}%
\else
\if@hyperrefloaded
\FirstUpcase{\zref@extract{#1}{counter}} \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{childcountervalue}} of \FirstUpcase{\zref@extract{#1}{parentcountername}} \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{parentcountervalue}}%
\else
\FirstUpcase{\zref@extract{#1}{counter}} \zref@extract{#1}{childcountervalue} of \FirstUpcase{\zref@extract{#1}{parentcountername}} \zref@extract{#1}{parentcountervalue}%
\fi
\fi
}%
}
% Command for lowercase output
\NewDocumentCommand{\parentcref}{m}{%
\zref@ifrefundefined{#1}{%
\cref{#1}%
}{%
\edef\@tmpb@{\zref@extract{#1}{parentcountervalue}}%
\edef\@tmpa@{\csname the\zref@extract{#1}{parentcountername}\endcsname}%
\ifx\@tmpb@\@tmpa@
\Cref{#1}%
\else
\if@hyperrefloaded
\zref@extract{#1}{counter} \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{childcountervalue}} of \zref@extract{#1}{parentcountername} \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{parentcountervalue}}%
\else
\zref@extract{#1}{counter} \zref@extract{#1}{childcountervalue} of \zref@extract{#1}{parentcountername} \zref@extract{#1}{parentcountervalue}%
\fi
\fi
}%
}
\makeatother
\GetAllResetLists
\RegisterPostLabelHook{\zlabel}
\begin{document}
\chapter{Chapter One}
Please look at \parentCref{othersection} or at \parentCref{foosubsection} or at \parentcref{foosubsection}
\section{Section One.One}
\label{mysection}
\lipsum
\section{Section One.Two}
\subsection{A subsection} \label{foosubsection}
Please ignore \parentCref{mysection}.
\chapter{Chapter Two}
\section{Section Two.One}
As you may have noticed, \parentCref{mysection} is useless.
\chapter{Chapter Three}
\section{Section Three.One} %
\section{Section Three.Two}\label{othersection}
\end{document}
cleveref
, I think. Apart from Mico's link, see tex.stackexchange.com/questions/346918/… (also an answer by me)