Как проверить, является ли запись `country = {}` пустой в пользовательской библиотеке BibLaTeX?

Как проверить, является ли запись `country = {}` пустой в пользовательской библиотеке BibLaTeX?

Я создал библиотеку BibLaTeX, которую использую для организации всех своих устных и постерных презентаций. Это фактически настраиваемая библиотека с новыми типами данных и командами цитирования. Все идеи я взял изздесьиздесь.

После некоторого времени программирования я получил следующий код, который работает довольно хорошо. Я могу использовать свою собственную команду \printcontrib{BiB_entry}в любом тексте, но также я могу сделать некоторый листинг в конце, например, вызвав все записи Bib через последнюю команду. Прежде чем я покажу код, я хотел бы извиниться уже здесь, что мой код, вероятно, является каким-то (злым?) хаком. ;-)

МВЭ

\RequirePackage{filecontents}


% The BibTeX library
\begin{filecontents*}{\jobname.bib}
@Contribution{Oral_2016_1,
  Type      = {Oral},
  Invited   = {True},
  Author    = {{\textbf{Author, One} and Author, Two and Author, Three}},
  Presenter = {{Author, One}},
  Title     = {{Some cool stuff about the Nanoworld}},
  Event     = {{Conference about XYZ}},
  Eventtype = {Conference},
  Place     = {},
  City      = {Helsinki (Finland) - Stockholm (Sweden)},
  Country   = {},
  Date      = {May 1$^{\rm st}$ - June 2$^{\rm nd}$},
  Period    = {},
  Year      = {2016},
  Note      = {}
}

@Contribution{Oral_2015_1,
  Type      = {Oral},
  Invited   = {Ture},
  Author    = {{\textbf{Author, One}}},
  Presenter = {{Author, One}},
  Title     = {{Exciting research on cool Nanostuff}},
  Event     = {{6$^{\rm th}$ Nanotechnology workshop}},
  Eventtype = {Workshop},
  Place     = {},
  City      = {Giessen},
  Country   = {Germany},
  Date      = {September 24$^{\rm th}$},
  Period    = {},
  Year      = {2015},
  Note      = {}
}

@Contribution{Oral_2015_2,
  Type      = {Oral},
  Invited   = {False},
  Author    = {{Author, One and Author, Two and \textbf{Author, Three}}},
  Presenter = {{Author, Three}},
  Title     = {{Nanochemistry at its edge}},
  Event     = {{18$^{\rm th}$ Summer School of Nanochemistry}},
  Eventtype = {School},
  Place     = {},
  City      = {Cassis},
  Country   = {France},
  Date      = {September 9$^{\rm th}$},
  Period    = {},
  Year      = {2015},
  Note      = {}
}
\end{filecontents*}

% The declaration of the entries.
\begin{filecontents}{contribution.dbx}
\DeclareDatamodelEntrytypes{contribution}
\DeclareDatamodelFields[type=field,datatype=literal]{
  type,
  invited,
  title,
  event,
  eventtype,
  place,
  city,
  country,
  date,
  period,
  year,
  note
}

\DeclareDatamodelFields[type=list,datatype=name]{
  author,
  presenter
}
\DeclareDatamodelEntryfields[contribution]{
  type,
  invited,
  author,
  presenter,
  title,
  event,
  eventtype,
  place,
  city,
  country,
  date,
  period,
  year,
  note}
\end{filecontents}



% The standard LaTeX head, with a link to the chem-acs style and biber. The
% datamodel 'contribution' is also declared.
\documentclass[english]{book}
\usepackage{babel}
\usepackage{ifmtarg}
\usepackage{xstring}
\usepackage{ifthen}
\usepackage[datamodel=contribution,
            style=chem-acs,
            natbib=true,
            backend=biber]
           {biblatex}
\addbibresource{\jobname.bib}



% Declare cite commands, the most important ones. Others will be added.
\DeclareCiteCommand{\citeevent}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext{\printfield{event}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citedate}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext{\printfield{date}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citeyear}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext{\printfield{year}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citecity}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext{\printfield{city}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citecountry}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext{\printfield{country}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citetitle}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext{\printfield{title}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand*{\citeauthor}
    {\defcounter{maxnames}{99}%
     \defcounter{minnames}{99}%
     \defcounter{uniquename}{2}%
     \boolfalse{citetracker}%
     \boolfalse{pagetracker}%
     \usebibmacro{prenote}}
    {\ifciteindex{\indexnames{labelname}}{}\printnames{labelname}}
    {\multicitedelim}
    {\usebibmacro{postnote}}




% My own command, which puts into format and prints the contribution.
\newcommand{\printcontrib}[1]{
    \citeauthor*{#1}, 
    \citetitle*{#1}, 
    \citeevent{#1},
    \citecity{#1} 
%
%   This works, but there is no 'if' that might find an empty 'country' field.
%   I would like to have:
%   If  : Country   = {} => Do not print '(\citecountry{#1})' 
%   Else: print (\citecountry{#1})
    (\citecountry{#1}),
%
%
%   Here is my first test amongst many others:
%   It works but there is a error: "! Illegal unit of measure (pt inserted)." 
%
%   \newlength{\strlen}\settowidth{\strlen}{\citecountry{#1}}
%   \ifdim\strlen=0\else(\citecountry{#1})\fi,
%   \let\strlen\relax 
%    
    \citedate{#1} (\citeyear{#1})
} 




\begin{document}

\chapter{Oral contributions}

\printcontrib{Oral_2016_1}\\\\
%
\noindent\printcontrib{Oral_2015_2}\\\\
%
\noindent\printcontrib{Oral_2015_1}\\\\
%

\end{document}

Вывод выглядит так: Вывод кода выше

Пока все хорошо. Теперь в одной записи BibLaTeX могут быть некоторые записи (см., например, Oral_2016_1 => Country = {}), в которых нет текста внутри двух {}, поскольку некоторая информация отсутствует (обратите внимание, что я хотел бы сохранить эти скобки по нескольким причинам ... .)

Я хотел бы иметь часть 'if ... do ... else do ...' в коде, которая проверяет, является ли запись 'пустой', поэтому здесь Country = {}. В противном случае, как в данном случае, в тексте отображаются две скобки ().

Я хотел бы иметь это условие, в частности, в этой команде:

% My own command, which puts into format and prints the contribution.
\newcommand{\printcontrib}[1]{
    \citeauthor*{#1}, 
    \citetitle*{#1}, 
    \citeevent{#1},
    \citecity{#1} 
%
%   This works, but there is no 'if' that might find an empty 'country' field.
%   I would like to have:
%   If  : Country   = {} => Do not print '(\citecountry{#1})' 
%   Else: print (\citecountry{#1})
    (\citecountry{#1}),
%
%
%   Here is my first test amongst many others:
%   It works but there is a error: "! Illegal unit of measure (pt inserted)." 
%
%   \newlength{\strlen}\settowidth{\strlen}{\citecountry{#1}}
%   \ifdim\strlen=0\else(\citecountry{#1})\fi,
%   \let\strlen\relax 
%    
    \citedate{#1} (\citeyear{#1})
} 

Команда (\citecountry{#1})(обратите внимание на скобки (и )) будет выполнена только в том случае, если запись countryсодержит какой-либо текст, другими словами, отсутствует Country = {}в файле BibLaTeX.

Я перепробовал дюжину вещей. Например, я пробовал несколько условий if с помощью пакетов ifmtarg, xstringи ifthen, но безуспешно. Единственное half-solutionв кавычках % (под текстом % Here is my first testв MWE) работает, хотя и с ошибками (вам нужно раскомментировать это, чтобы оно скомпилировалось LaTeX).

решение1

В biblatex, форматирование полей, такое как скобки, выделение или курсив, в большинстве случаев не следует записывать в макрос напрямую, их следует выполнять с помощью \DeclareFieldFormat. Таким образом, вы можете быть уверены, что biblatexсможете правильно определять пустые поля и ничего не делать в этом случае.

Вы могли бы просто сделать

\DeclareFieldFormat{country}{\mkbibparens{#1}}

\DeclareCiteCommand{\citecountry}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printfield{country}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

Поле затем оборачивается скобками всякий раз, когда оно отображается, и игнорируется в противном случае. Обратите внимание, что нет необходимости оборачивать один \printfieldв \printtextбез аргумента, \printfield{country}будет делать то же самое, что и \printtext{\printfield{country}}.

Вместо того, чтобы определять \citecontribтак, как вы делаете сейчас, вам, вероятно, следует просто определить драйвер библиографии, например, @contributionтак (это всего лишь первый грубый набросок, но вы поняли идею)

\DeclareFieldFormat{country}{\mkbibparens{#1}}
\DeclareFieldFormat[contribution]{title}{\mkbibemph{#1}}

\newbibmacro*{event+venue+city+country+date}{%
  \printfield{eventtitle}%
  \newunit
  \printfield{eventtitleaddon}%
  \newunit
  \printeventdate
  \newunit
  \printfield{city}
  \setunit{\addspace}%
  \printfield{country}
  \newunit}

\DeclareBibliographyDriver{contribution}{%
  \usebibmacro{bibindex}%
  \usebibmacro{begentry}%
  \usebibmacro{author/editor+others/translator+others}%
  \setunit{\printdelim{nametitledelim}}\newblock
  \usebibmacro{title}%
  \newunit
  \printlist{language}%
  \newunit\newblock
  \usebibmacro{byauthor}%
  \newunit\newblock
  \usebibmacro{event+venue+city+country+date}%
  \newunit\newblock
  \printfield{howpublished}%
  \newunit\newblock
  \printfield{note}%
  \newunit\newblock
  \usebibmacro{location+date}\printdate%
  \newunit\newblock
  \iftoggle{bbx:url}
    {\usebibmacro{url+urldate}}
    {}%
  \newunit\newblock
  \usebibmacro{addendum+pubstate}%
  \setunit{\bibpagerefpunct}\newblock
  \usebibmacro{pageref}%
  \newunit\newblock
  \iftoggle{bbx:related}
    {\usebibmacro{related:init}%
     \usebibmacro{related}}
    {}%
  \usebibmacro{finentry}}

Затем вы можете просто использовать его \fullciteи все готово.

решение2

Вам следует проверить, существует ли поле как часть \DeclareCiteCommandиспользования\iffieldundef или что-то подобное; см. раздел4.6.2 Отдельные тестывbiblatex документация):

\DeclareCiteCommand{\citecountry}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\iffieldundef{country}{}{(\printtext{\printfield{country}})}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

и вот \printcontrib:

\newcommand{\printcontrib}[1]{%
  \citeauthor*{#1}, 
  \citetitle*{#1}, 
  \citeevent{#1},
  \citecity{#1} 
  \citecountry{#1},
  \citedate{#1} (\citeyear{#1})
} 

Вы также можете написать более крупное \DeclareCiteCommandрешение, используя \printcontrib.

введите описание изображения здесь

Связанный контент