如何使用 BibLaTeX/Biber 创建全新的数据类型?

如何使用 BibLaTeX/Biber 创建全新的数据类型?

标题非常直观。我需要类似的东西向 biblatex 条目添加新字段,而是针对全新的条目类型。(IIUC,链接只是将一种类型转移到另一种类型上。)

我正在尝试定义一种@stackexchange可以引用 StackExchange 问题的类型:

@stackexchange{se:l3help,
  sitekey = {tex},
  % sitetopic = {\TeX, \LaTeX, Con\TeX t, and related typesetting systems},
  askid   = {45838},
  title   = {What can \textit{I} do to help the \LaTeX3 Project},
  askdate = {2012/02/26}
}

其中id必须与正则表达式匹配[0-9]+asked是日期, 并sitekey提供到适当位置的硬编码映射(sitetopic如果可用)。 如果sitekey不可用,则sitetopic是必需的。 如果sitetopic提供,则它将覆盖 的映射sitekeyidtitleasked都是必需的。

如果您认为应该包括任何其他字段,请随意;我尝试将数据类型缩减为“特殊”数据类型。我希望这个问题可以涵盖字段可以采取的不同方式的大部分基础。

MWE(根据评论改编)

\begin{filecontents}{references.bib}
@stackexchange{se:l3help,
    sitetopic = {tex},
    title   = {What can \textit{I} do to help the \LaTeX3 Project},
    askdate = {2012/02/26},
    askid   = {45838},
    askp    = {Brent Longorough},
    askerid = 344,
    ansp    = {Frank Mittelbach},
    anspid  = 10109,
    ansdate = {2012/03/01},
    ansid   = 46427
  }
\end{filecontents}
\begin{filecontents}{stackexchange.dbx}
\DeclareDatamodelEntrytypes{stackexchange}
\DeclareDatamodelFields{
  sitekey,
  sitetopic,
  askdate,
  askedit,
  askid,
  askp,
  askpid,
  ansp,
  anspid,
  ansid,
  ansdate,
  ansedit}
\DeclareDatamodelEntryfields[stackexchange]{
  sitekey,
  sitetopic,
  askdate,
  askedit,
  askid,
  askp,
  askpid,
  ansp,
  anspid,
  ansid,
  ansdate,
  ansedit,
  title}
\end{filecontents}
\documentclass{article}

\usepackage{csquotes}
\usepackage[datamodel=stackexchange,backend=biber]{biblatex}
\addbibresource{references.bib}

\newbibmacro*{stackexchangequestion}{%
  \mkbibquote{\printfield{title}}
  \mkbibparens{\printfield{askid}}
  \addperiod
}

\newbibmacro*{stackexchangeask}{%
  Asked \mkbibdatelong{\printfield{askdate}}%
    \iffieldundef{askedit}{}{ \mkbibparens{edited \mkbibdatelong{\printfield{askedit}}}}%
  by
  \printfield{askp} \mkbibparens{\printfield{askpid}}
  \addperiod
}

\newbibmacro*{stackexchangeans}{%
  Answered \mkbibdatelong{\printfield{ansdate}}%
    \iffieldundef{ansedit}{}{ \mkbibparens{edited \mkbibdatelong{\printfield{ansedit}}}}%
  by
  \printfield{ansp} \mkbibparens{\printfield{anspid}}
  \addperiod
}

\newbibmacro*{stackexchangesite}{%
  \printfield{sitetopic}}

\DeclareBibliographyDriver{stackexchange}{%
  \usebibmacro{bibindex}%
  \usebibmacro{begentry}%
  \usebibmacro{stackexchangequestion}%
  \usebibmacro{stackexchangeask}%
  \usebibmacro{stackexchangeans}%
  \usebibmacro{stackexchangesite}%
  \usebibmacro{finentry}}

\begin{document}

\cite{se:l3help}

\printbibliography
\end{document}

引发Missing \endcsname错误,可能是由于误用造成的\usebibmacro

答案1

答案现已更新,以适应较新biblatex版本(>= 3.6)中的日期处理,以前必须手动完成的许多工作现在将自动完成。请查看早期版本的编辑历史记录。

这是一个相当全面的问题,但我还是会尝试回答。这个答案主要涉及参考书目输出。对于引用,可能需要进行额外的修改和配置,但需要做什么在很大程度上取决于所使用的样式,没有通用的答案。对于numeric引用样式,下面的示例当然可以在不进一步修改的情况下工作。

声明新字段以及新条目类型及其字段

首先,在声明数据模型时,我们需要确保biblatex真正知道我们声明的字段/列表的类型(这是通过可选参数来完成的\DeclareDatamodelFields)。你可以在 §4.5.4 中阅读更多关于此内容的内容数据模型规范,第 212 页biblatex文档

输入字段主要有两种类型:fieldlistfields 通常保存一个值,而lists 可以保存多个项目,中间用 分隔and.bib(另请参阅§2.2.1数据类型,第 15 页)。

我将sitekey和声明sitetopic为文字字段(例如title字段)。 askpansp显然是名称列表(即使在这种情况下,列表可能只会包含一个项目)。 您要求的许多字段似乎都与日期有关,因此有askdateansdateaskeditdateanseditdate它们的dateparts(将自动创建,但仍需要手动添加\DeclareDatamodelEntryfields)。 最后,我决定ids 应该是逐字字段。

\begin{filecontents}{stackexchange.dbx}
\DeclareDatamodelEntrytypes{stackexchange}
\DeclareDatamodelFields[type=field,datatype=literal]{
  sitekey,
  sitetopic,
}
\DeclareDatamodelFields[type=list,datatype=name]{
  askp,
  ansp,
}
\DeclareDatamodelFields[type=field, datatype=date, skipout]{
  askdate,
  ansdate,
  askeditdate,
  anseditdate}
\DeclareDatamodelFields[type=field, datatype=verbatim]{
  askid,
  askpid,
  anspid,
  ansid,
}
\DeclareDatamodelEntryfields[stackexchange]{
  sitekey,
  sitetopic,
  askid,
  askp,
  askpid,
  ansp,
  anspid,
  ansid,
  askyear,
  askmonth,
  askday,
  ansyear,
  ansmonth,
  ansday,
  askedityear,
  askeditmonth,
  askeditday,
  ansedityear,
  anseditmonth,
  anseditday,
  title}
\end{filecontents}

\DeclareDatamodelEntryfields只是使那些@stackexchange与该条目类型相关的字段变得已知。

声明新的参考书目字符串(如有必要)

我们还想显示“询问”和“回答”等单词,而不是对它们进行硬编码,使用.lbx文件进行本地化才是可行的方法。只有当您希望在输出中包含字符串时才需要这样做。没有必要为您定义的每个字段都包含一个字符串。一些 bibstring 的名称与某些字段的名称重合这一事实纯属偶然。不需要为某些字段类型定义 bibstring。

定义新字符串的最完整方法是通过文件.lbx,因为该方法允许您定义字符串的长格式和短格式。您也可以直接在前言中定义新字符串,但这样您只能给出一种格式,即短格式和长格式。

我们的新本地化文件english-stack.lbx继承了所有内容,english.lbx但添加了askedanswerededited作为字符串。

\begin{filecontents*}{english-stack.lbx}
  \ProvidesFile{english-stack.lbx}[2014/05/07 english with additions for stackexchange]
  \InheritBibliographyExtras{english}
  \NewBibliographyString{asked,answered,edited}
  \DeclareBibliographyStrings{%
    inherit   = {english},
    asked     = {{asked}{asked}},
    answered  = {{answered}{answered}},
    edited    = {{edited}{edited}},
  }
\end{filecontents*}

我们必须告诉biblatex使用该语言定义

\DeclareLanguageMapping{english}{english-stack}

定义书目输出

最后,我们可以继续定义书目驱动程序。书目驱动程序是决定如何在书目中打印条目的主要定义。书目驱动程序通常由对几个书目宏的调用以及对标点符号和打印命令的调用组成。

字段格式

字段格式定义每个打印字段的格式。我们避免硬编码任何内容,并使用 提供的宏biblatex

因此,我们定义字段格式来代替换行。我们使用\printfield{title}标点符号和s 来代替硬编码的单词。\mkbibquote\setunit\bibstring

\DeclareFieldFormat[stackexchange]{title}{\mkbibquote{#1\isdot}}
\DeclareFieldFormat{askpid}{%
  \mkbibparens{\ifhyperref
    {\href{http://tex.stackexchange.com/users/#1}{\nolinkurl{#1}}}
    {\nolinkurl{#1}}}}
    
\DeclareFieldFormat{anspid}{%
  \mkbibparens{\ifhyperref
    {\href{http://tex.stackexchange.com/users/#1}{\nolinkurl{#1}}}
    {\nolinkurl{#1}}}}
    
\DeclareFieldFormat{askid}{%
  \mkbibparens{\ifhyperref
    {\href{http://tex.stackexchange.com/q/#1}{\nolinkurl{#1}}}
    {\nolinkurl{#1}}}}
    
\DeclareFieldFormat{ansid}{%
  \mkbibparens{\ifhyperref
    {\href{http://tex.stackexchange.com/a/#1}{\nolinkurl{#1}}}
    {\nolinkurl{#1}}}}

作为额外的奖励,这些id字段现在链接到正确的 stackexchange 网站。

\newbibmacro*{stackexchangequestion}{%
  \printfield{title}%
  \setunit{\addspace}%
  \printfield{askid}%
}

书目宏

可以使用书目宏来划分输出定义。

命令不应采用任何格式\printfield,格式由 处理\DeclareFieldFormat

\newbibmacro*{stackexchangeask}{%
  \bibstring{asked}%
  \setunit{\addspace}%
  \printaskdate%
  \iffieldundef{askedityear}%
    {}
    {\printtext[parens]{%
       \bibstring{edited}%
       \setunit{\addspace}%
       \printaskeditdate}}%
  \setunit{\addspace}%
  \bibstring{byauthor}%
  \setunit{\addspace}%
  \printnames{askp}%
  \setunit{\addspace}%
  \printfield{askpid}%
}

\newbibmacro*{stackexchangeans}{%
  \bibstring{answered}%
  \setunit{\addspace}%
  \printansdate%
  \iffieldundef{ansedityear}
    {}
    {\printtext[parens]{%
       \bibstring{edited}%
       \setunit{\addspace}%
       \printanseditdate}}%
  \setunit{\addspace}%
  \bibstring{byauthor}%
  \setunit{\addspace}%
  \printnames{ansp}%
  \setunit{\addspace}%
  \printfield{anspid}%
}

\newbibmacro*{stackexchangesite}{%
  \printfield{sitetopic}}

参考书目驱动程序

驱动程序定义最终的输出结构。通常,驱动程序会大量使用 bibmacros,但它不必这样做。

\DeclareBibliographyDriver{stackexchange}{%
  \usebibmacro{bibindex}%
  \usebibmacro{begentry}%
  \usebibmacro{stackexchangequestion}%
  \newunit\newblock
  \usebibmacro{stackexchangeask}%
  \newunit\newblock
  \usebibmacro{stackexchangeans}%
  \newunit\newblock
  \usebibmacro{stackexchangesite}%
  \newunit\newblock
  \usebibmacro{finentry}}

平均能量损失

\RequirePackage{filecontents}
\begin{filecontents*}{\jobname.bib}
@stackexchange{se:l3help,
  sitetopic = {tex},
  title   = {What can \textit{I} do to help the \LaTeX3 Project},
  askdate = {2012-02-26},
  askid   = {45838},
  askp    = {Brent Longorough},
  askpid  = {344},
  ansp    = {Frank Mittelbach},
  anspid  = {10109},
  ansdate = {2012-03-01},
  ansid   = {46427},
}
\end{filecontents*}
\begin{filecontents}{stackexchange.dbx}
\DeclareDatamodelEntrytypes{stackexchange}
\DeclareDatamodelFields[type=field,datatype=literal]{
  sitekey,
  sitetopic,
}
\DeclareDatamodelFields[type=list,datatype=name]{
  askp,
  ansp,
}
\DeclareDatamodelFields[type=field, datatype=date, skipout]{
  askdate,
  ansdate,
  askeditdate,
  anseditdate}
\DeclareDatamodelFields[type=field, datatype=verbatim]{
  askid,
  askpid,
  anspid,
  ansid,
}
\DeclareDatamodelEntryfields[stackexchange]{
  sitekey,
  sitetopic,
  askid,
  askp,
  askpid,
  ansp,
  anspid,
  ansid,
  askyear,
  askmonth,
  askday,
  ansyear,
  ansmonth,
  ansday,
  askedityear,
  askeditmonth,
  askeditday,
  ansedityear,
  anseditmonth,
  anseditday,
  title}
\end{filecontents}
\documentclass[english]{article}
\usepackage{babel}
\usepackage{csquotes}
\usepackage[datamodel=stackexchange,backend=biber]{biblatex}
\usepackage{hyperref}
\addbibresource{\jobname.bib}

\begin{filecontents*}{english-stack.lbx}
  \ProvidesFile{english-stack.lbx}[2014/05/07 english with additions for stackexchange]
  \InheritBibliographyExtras{english}
  \NewBibliographyString{asked,answered,edited}
  \DeclareBibliographyStrings{%
    inherit   = {english},
    asked     = {{asked}{asked}},
    answered  = {{answered}{answered}},
    edited    = {{edited}{edited}},
  }
\end{filecontents*}
\DeclareLanguageMapping{english}{english-stack}

\DeclareFieldFormat[stackexchange]{title}{\mkbibquote{#1\isdot}}
\DeclareFieldFormat{askpid}{%
  \mkbibparens{\ifhyperref
    {\href{http://tex.stackexchange.com/users/#1}{\nolinkurl{#1}}}
    {\nolinkurl{#1}}}}
    
\DeclareFieldFormat{anspid}{%
  \mkbibparens{\ifhyperref
    {\href{http://tex.stackexchange.com/users/#1}{\nolinkurl{#1}}}
    {\nolinkurl{#1}}}}
    
\DeclareFieldFormat{askid}{%
  \mkbibparens{\ifhyperref
    {\href{http://tex.stackexchange.com/q/#1}{\nolinkurl{#1}}}
    {\nolinkurl{#1}}}}
    
\DeclareFieldFormat{ansid}{%
  \mkbibparens{\ifhyperref
    {\href{http://tex.stackexchange.com/a/#1}{\nolinkurl{#1}}}
    {\nolinkurl{#1}}}}

\newbibmacro*{stackexchangequestion}{%
  \printfield{title}%
  \setunit{\addspace}%
  \printfield{askid}%
}

\newbibmacro*{stackexchangeask}{%
  \bibstring{asked}%
  \setunit{\addspace}%
  \printaskdate%
  \iffieldundef{askedityear}%
    {}
    {\printtext[parens]{%
       \bibstring{edited}%
       \setunit{\addspace}%
       \printaskeditdate}}%
  \setunit{\addspace}%
  \bibstring{byauthor}%
  \setunit{\addspace}%
  \printnames{askp}%
  \setunit{\addspace}%
  \printfield{askpid}%
}

\newbibmacro*{stackexchangeans}{%
  \bibstring{answered}%
  \setunit{\addspace}%
  \printansdate%
  \iffieldundef{ansedityear}
    {}
    {\printtext[parens]{%
       \bibstring{edited}%
       \setunit{\addspace}%
       \printanseditdate}}%
  \setunit{\addspace}%
  \bibstring{byauthor}%
  \setunit{\addspace}%
  \printnames{ansp}%
  \setunit{\addspace}%
  \printfield{anspid}%
}

\newbibmacro*{stackexchangesite}{%
  \printfield{sitetopic}}

\DeclareBibliographyDriver{stackexchange}{%
  \usebibmacro{bibindex}%
  \usebibmacro{begentry}%
  \usebibmacro{stackexchangequestion}%
  \newunit\newblock
  \usebibmacro{stackexchangeask}%
  \newunit\newblock
  \usebibmacro{stackexchangeans}%
  \newunit\newblock
  \usebibmacro{stackexchangesite}%
  \newunit\newblock
  \usebibmacro{finentry}}

\begin{document}
\nocite{*}
\cite{se:l3help}

\printbibliography
\end{document}

在此处输入图片描述


为了允许使用askdate标签日期,因此authoryear样式(和其他类似样式)不会打印“nd”,我们可以使用\DeclareLabeldate(§4.5.11特殊字段,第 238 页)如下

\DeclareLabeldate{%
  \field{date}
  \field{eventdate}
  \field{origdate}
  \field{askdate}
  \field{urldate}
  \literal{nodate}
}

\DeclareLabelname如果您想以/样式中的作者身份askp查看,还有(第 238 页) 具有类似的语法。anspauthoryearauthortitle

相关内容