根据列表创建书目类别和标题

根据列表创建书目类别和标题

我希望能够指定一个列表,用于创建类别并向其中添加条目。

我使用 pgffor 来以方便的方式指定类别名称和标题。我在此示例中使用的类别是任意的,但字段值和类别的一般使用则不是。

平均能量损失

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[defernumbers=true,sorting=ydnt,doi=false,eprint=false,isbn=false]{biblatex}
\renewcommand*{\bibfont}{\footnotesize}
\usepackage{pgffor}

\xdef\bibcats{}

\newcommand*{\addcat}[2]{%
  \DeclareBibliographyCategory{#1}%
  \defbibheading{#1}{\subsection*{#2}}%
}

\foreach \catg/\head in {phdthesis/PhD. Thesis,article/Articles}{%
  \edef\tmp{\noexpand\addcat{\catg}{\head}}
  \tmp
  \listxadd{\bibcats}{\catg}
}

\addbibresource{biblatex-examples.bib}

\AtDataInput{%
  \ifboolexpr{%
    not test {\iffieldundef{type}}
    and
    test {\xifinlist{\thefield{type}}{\bibcats}}
  }
    {\addtocategory{\strfield{type}}{\strfield{entrykey}}}%
    {\ifboolexpr{%
        test {\ifnumgreater{\thefield{year}}{2000}}
        and
        test {\xifinlist{\thefield{entrytype}}{\bibcats}}
      }%
      {\addtocategory{\strfield{entrytype}}{\strfield{entrykey}}}%
      {}%
    }%
}

\begin{document}

\nocite{*}

\printbibheading
\bibbycategory

\end{document}

结果

除了设置标题外,上述操作均有效,并会引发错误,Package biblatex Error: Heading <phdthesis/article> could not be found.导致:

foreach 循环结果

期望结果

我希望通过将 foreach 循环替换为

\addcat{phdthesis}{PhD. Thesis}
\addcat{article}{Articles}
\forcsvlist{\listxadd\bibcats}{phdthesis,article}

给予

没有 foreach 循环

问题

我希望类别的创建依赖于列表。鉴于非 foreach 循环方法有效,我怀疑问题主要来自扩展问题。

  • 如何根据列表创建类别和相应的标题?
  • 为什么我尝试过的处理扩展的方法不起作用?

答案1

我认为问题在于您\defbibheading正在一个组中执行,因此在那里定义的命令(用\newcommand)在您需要时不可用。

从 egreg 的答案中窃取全局 renewcommand 的代码定义这样的命令,我们重新定义了 biblatex 的内部工作原理,\defbibheading以利用这种全局重新定义:

\makeatletter
\def\gnewcommand{\g@star@or@long\gnew@command}
\def\grenewcommand{\g@star@or@long\grenew@command}
\def\g@star@or@long#1{% 
  \@ifstar{\let\l@ngrel@x\global#1}{\def\l@ngrel@x{\long\global}#1}}
\def\gnew@command#1{\@testopt{\@gnewcommand#1}0}
\def\@gnewcommand#1[#2]{%
  \kernel@ifnextchar [{\@gxargdef#1[#2]}%
                {\@argdef#1[#2]}}
\let\@gxargdef\@xargdef
\patchcmd{\@gxargdef}{\def}{\gdef}{}{}
\let\grenew@command\renew@command
\patchcmd{\grenew@command}{\new@command}{\gnew@command}{}{}

\def\blx@defbibheading#1[#2]{%
  \csundef{#1}%
  \expandafter\gnewcommand\csname#1\endcsname[1][#2]}
\makeatother

现在一切都按预期工作了。我不知道是否有其他方法可以避免循环在组内执行并隐藏重新定义。

相关内容