![如何使用 biblatex 和 biber 检测传递给自定义 cite 命令的引用键数量](https://linux22.com/image/409190/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%20biblatex%20%E5%92%8C%20biber%20%E6%A3%80%E6%B5%8B%E4%BC%A0%E9%80%92%E7%BB%99%E8%87%AA%E5%AE%9A%E4%B9%89%20cite%20%E5%91%BD%E4%BB%A4%E7%9A%84%E5%BC%95%E7%94%A8%E9%94%AE%E6%95%B0%E9%87%8F.png)
我正在研究如何利用biblatex+biber
灵活性和模块化来创建引用系统以引用法律条款(法律、法令等的部分内容)。为此,我创建了自定义数据模型、参考书目驱动程序的(粗略)草稿,现在我正在研究自定义引用命令。
遗憾的是,这让 MWE 变得相当冗长。
我想知道,是否有可能检测出键传递给自定义cite
命令,以改变输出。规则:
- 1钥匙, 不用找了
- 2钥匙s,单独引用和文本(例如
" and"
:) - 3钥匙s,单独引用空间和逗号
- 4 个或以上钥匙s,压缩引用,只在正文中打印第一个和最后一个,其他的只放在参考书目中
这是我想要实现的一套完整的规则,但实际上,如果能够检测到钥匙传递给cite
命令,如果有人能帮助我,并提示我如何进行第 2 步,我很乐意将第 3 步和第 4 步作为练习来执行。
梅威瑟:
% arara: lualatex
% arara: biber
% arara: lualatex
% arara: biber
% arara: lualatex
\documentclass [a4paper, 11pt, twoside, openright, czech]{scrbook}
\usepackage [czech,shorthands=off] {babel}
\usepackage{fontspec}
\usepackage{filecontents}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{lmodern}
\usepackage{csquotes}
\begin{filecontents}{speclegislation.dbx}
\DeclareDatamodelEntrytypes{speclegislation}
\DeclareDatamodelFields[type=field,datatype=literal]{
dokument,
zkracene,
number,
year,
title,
paragraf,
odstavec,
pismeno,
sortkey,
}
\DeclareDatamodelEntryfields[speclegislation]{
dokument,
zkracene,
number,
year,
title,
paragraf,
odstavec,
pismeno,
keywords,
sortkey,
}
\end{filecontents}
\usepackage[style=numeric, backend=biber, datamodel=speclegislation, refsegment=chapter, defernumbers=true, mincrossrefs=1, backref=true, backrefstyle=three, sorting=none]{biblatex}
\newbibmacro{dokumentnumberyeartitle}{
\printfield{dokument}%
\newunit
\printfield{number}%
\newblock
\printfield{year}%
\newunit
\printfield{title}
}
\newbibmacro{paragrafodstavecpismeno}{
\printfield{paragraf} %
\nopunct\newunit
\printfield{odstavec} %
\nopunct\newunit
\printfield{pismeno}%
}
\DeclareBibliographyDriver{speclegislation}{%
\usebibmacro{bibindex}%
\usebibmacro{begentry}%
\usebibmacro{dokumentnumberyeartitle}
\nopunct\newunit
\usebibmacro{paragrafodstavecpismeno}
\nopunct\newunit
\usebibmacro{pageref}%
\iftoggle{bbx:related}
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
\usebibmacro{finentry}}
\DeclareSourcemap{
\maps[datatype=bibtex,overwrite=true]{
\map{
\pertype{speclegislation}
\step[fieldsource=paragraf]
\step[fieldset=sortkey, origfieldval]
}
}
}
\DeclareFieldFormat{dokument}{#1\addspace}
\DeclareFieldFormat{number}{#1/}
\DeclareFieldFormat{year}{#1\addnbspace Sb.,\addspace}
\DeclareFieldFormat{title}{#1\addspace}
\DeclareFieldFormat{paragraf}{§\addnbspace#1\addspace}
\DeclareFieldFormat{odstavec}{odst.\addnbspace#1\addspace}
\DeclareFieldFormat{pismeno}{písm.\addnbspace#1)\addspace}
\DeclareFieldFormat{zkracene}{#1\addspace}
\renewcommand{\finentrypunct}{}
\DefineBibliographyStrings{czech}{
bibliography = {Reference},
}
\begin{filecontents}{citace.bib}
@speclegislation{v21p12pa,
paragraf = {12},
pismeno = {a},
keywords = {vyhlaska21},
crossref = {v21}
}
@speclegislation{v21p12pb,
paragraf = {12},
pismeno = {b},
keywords = {vyhlaska21},
crossref = {v21}
}
@speclegislation{v21p12pc,
paragraf = {12},
pismeno = {c},
keywords = {vyhlaska21},
crossref = {v21}
}
@speclegislation{v21p12pd,
paragraf = {12},
pismeno = {d},
keywords = {vyhlaska21},
crossref = {v21}
}
@speclegislation{v21p12pe,
paragraf = {12},
pismeno = {e},
keywords = {vyhlaska21},
crossref = {v21}
}
@speclegislation{v21p12pf,
paragraf = {12},
pismeno = {f},
keywords = {vyhlaska21},
crossref = {v21}
}
@speclegislation{v21,
dokument = {Vyhláška},
zkracene = {v.},
number = {21},
year = {2017},
title = {o zajišťování jaderné bezpečnosti JZ},
keywords = {vyhlaska21}
}
\end{filecontents}
\addbibresource{citace.bib}
\DeclareCiteCommand{parvcite}
{\usebibmacro{prenote}}
{\usebibmacro{citeindex}%
\usebibmacro{paragrafodstavecpismeno}\printfield{zkracene}\printfield{number}\printfield{year}%
\printtext[bibhyperref]{%
\printfield{labelprefix}%
\mkbibbrackets{\printfield{labelnumber}}}%
}
{\addcomma\addspace}
{\usebibmacro{postnote}}
\ExplSyntaxOn
\NewDocumentCommand{\mycite}{ O{} O{} m }{
\parvcite{#3}
}
\ExplSyntaxOff
\begin{document}
Citation testing:
Current output:
1 \textit{key} citation:
\mycite{v21p12pa}
\medskip
2 \textit{keys} citation
\mycite{v21p12pa, v21p12pb}
Desired output:
\mycite{v21p12pa} and \mycite{v21p12pb}
\medskip
3 \textit{key} citation:
\mycite{v21p12pa, v21p12pb, v21p12pc}
Desired output:
\mycite{v21p12pa}, \mycite{v21p12pb}, \mycite{v21p12pc}
\medskip
4 or more \textit{key}s citation:
\mycite{v21p12pa, v21p12pb, v21p12pc, v21p12pd}
Desired output:
\mycite{v21p12pa} \nocite{v21p12pb} \nocite{v21p12pc} – \mycite{v21p12pd}
\clearpage
\printbibliography
\end{document}
附言:部分文本是捷克语,希望您不介意。另外,mycite
命令“准备”变得更复杂/更复杂,这就是为什么它被定义为xparse
带有 2 个可选参数和 1 个强制参数的原因。
答案1
biblatex
\...cite
存储当前调用中引用的输入键数citetotal
和当前键的数目citecount
。使用这两个计数器,您应该能够实现您想要的功能。
请注意,还有multicitetotal
和multicitecount
来计数多引用命令中的输入键组的数量\...cites
。
biblatex
\iffirstcitekey{<true>}{<false>}
提供了开箱即用的测试\iflastcitekey{<true>}{<false>}
,因此您不必为这些常见情况编写数字比较测试,但是在下面的示例中我不会使用这两个命令。
以下 MWE 演示了如何citecount
在citetotal
简化设置中使用。
\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{csquotes}
\usepackage[style=numeric, backend=biber]{biblatex}
\addbibresource{biblatex-examples.bib}
\newcommand*{\mycitedelim}{%
\ifnumgreater{\value{citetotal}}{2}
{\addcomma\space}
{\addspace\bibstring{and}\space}}
\newbibmacro*{mycite}{%
\ifboolexpr{
test {\ifnumequal{\value{citecount}}{1}}
or test {\ifnumequal{\value{citecount}}{\value{citetotal}}}
or test {\ifnumless{\value{citetotal}}{4}}}
{\printtext[bibhyperref]{%
\printfield{labelprefix}%
\printfield{labelnumber}%
\ifbool{bbx:subentry}
{\printfield{entrysetcount}}
{}}}
{}}
\DeclareCiteCommand{\mycite}[\mkbibbrackets]
{\usebibmacro{prenote}}
{\usebibmacro{citeindex}%
\usebibmacro{mycite}}
{\setunit{\mycitedelim}}
{\usebibmacro{postnote}}
\begin{document}
\mycite{sigfridsson}
\mycite{sigfridsson,nussbaum}
\mycite{sigfridsson,nussbaum,worman}
\mycite{sigfridsson,nussbaum,worman,geer}
\mycite{sigfridsson,nussbaum,worman,geer,cicero}
\printbibliography
\end{document}
请注意,如果您希望正确压缩引文,则需要更复杂的方法,实际检查输出标签是否可以压缩(您可以将“12a、12b、12c、12d”压缩为“12a-12d”或“12a-d”,但不能将“12a、12b、14a、14e”压缩为“12a-14e”或“12a-e”)。这是在numeric-comp.cbx
对于简单的标签编号,但在您的使用案例中它可能会更加复杂。