4

I need to measure a number of characters in string, that I returned from label through \nameref command.

Here is my MWE:

\documentclass{article}

\usepackage{hyperref}
\usepackage{xstring}

\begin{document}

\protected\def\testStr{\nameref{testLabel}}
String content = \testStr
\par

\newlength\testStrWidth
\settowidth{\testStrWidth}{\testStr}
String width = \the\testStrWidth
\par

\StrLen{\testStr}[\testStrNumOfChars]
Number of characters in string = \testStrNumOfChars

\clearpage

\makeatletter
\edef\@currentlabelname{This is a somewhat long string}
\label{testLabel}
\makeatother

Here we have some text to make another page.

\end{document}

Here is the result:

MWE result

MWE doesn't give any errors. I'm using XeTeX, but it doesn't work in pdfLaTeX too. I've tried \edef, \def, \let instead of \protected\def, but nothing seems to work.

Of course, if I set tested string explicitly inside \StrLen command, everything will work as it should.

Any help would be much appreciated.

4

The \nameref command needs to be fully expanded into its textual form. To that end, you need to remove the hyperlinking that surrounds it, as that is what's causing the problems.

The following is marginally different from egreg's answer and uses e-TeX for conditioning on the existence of the reference - \r@<label>. All we're interested in is extracting the name/title. Nothing more...

enter image description here

\documentclass{article}

\usepackage{hyperref,xstring}
\newcommand{\thirdoffive}[5]{#3}% Similar to \@thirdoffive
% \assignnameref{<ref>}{<macro>}
\newcommand{\assignnameref}[2]{%
  \gdef#2{}% Assign macro to be blank
  \ifcsname r@#1\endcsname % If the reference exists...
    \xdef#2{\expandafter\expandafter\expandafter\thirdoffive\csname r@#1\endcsname}% ...grab the third argument - the name/title
  \fi
}
\begin{document}

\assignnameref{testLabel}{\testStr}%
String content = \testStr
\par

\newlength\testStrWidth
\settowidth{\testStrWidth}{\testStr}%
String width = \the\testStrWidth
\par

\StrLen{\testStr}[\testStrNumOfChars]%
Number of characters in string = \testStrNumOfChars

\clearpage

\makeatletter
\edef\@currentlabelname{This is a somewhat long string}
\label{testLabel}
\makeatother

Here we have some text to make another page.

\end{document}

Yes, \labels exist in the .aux file as macros in the form \r@<label> (via \newlabel). See Understanding how references and labels work.

  • Thanks for replay! So I can extract even another label attributes through this method. It will be really useful. – Andrei Borisov Mar 1 '16 at 1:31
  • @AndrewBohr: Yup. Based on hyperref, the first attribute is the reference number, the second attribute is the page number, the third attribute is the title, the fourth attribute is the hyperlink anchor, while the fifth attribute is left blank. – Werner Mar 1 '16 at 1:46
4

You need an expandable version of \nameref:

\documentclass{article}

\usepackage{xstring}
\usepackage{hyperref}

\makeatletter
\newcommand{\getnamereftext}[1]{%
  \@ifundefined{r@#1}{}{%
    \unexpanded\expandafter\expandafter\expandafter{%
      \expandafter\expandafter\expandafter\@thirdoffive\csname r@#1\endcsname
    }%
  }%
}

\begin{document}

\StrLen{\getnamereftext{testLabel}}[\testStrNumOfChars]
Number of characters in string = \testStrNumOfChars

\makeatletter
\edef\@currentlabelname{This is a somewhat long string}
\label{testLabel}
\makeatother

\end{document}

This will return 0 when the label is not yet defined.

enter image description here

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.