之前有一个问题询问 Biblatex 是否可以仅在条目不包含 DOI 的情况下打印条目的 ISBN。 接受的答案经过安德鲁·斯旺是使用 Biblatex 的源重映射功能来检查该doi
字段是否非空,如果是,则清除该isbn
字段以免打印。
此解决方案的问题在于它不适用于交叉引用的条目。例如,假设您有一个包含字段@proceedings
的条目isbn
,以及一个@inproceedings
包含字段 doi
和crossref
引用该条目的字段的条目@proceedings
。在这种情况下,当@inproceedings
在参考列表中打印条目时,会同时显示 DOI 和 ISBN。
这是一个最小的例子和输出:
\documentclass{article}
\usepackage[backend=biber]{biblatex}
\addbibresource{\jobname.bib}
\DeclareSourcemap{
\maps[datatype=bibtex]{
\map{
\step[fieldsource=doi,final]
\step[fieldset=isbn,null]
}
}
}
\begin{filecontents}{\jobname.bib}
@proceedings{book1,
editor = {Adam Author},
title = {Book One},
year = 2020,
doi = {10.1000/1010},
note = {DOI only},
}
@proceedings{book2,
editor = {Betty Bookwriter},
title = {Book Two},
year = 2020,
doi = {10.1000/2020},
isbn = {123-456-789},
note = {DOI and ISBN; ISBN should not be displayed},
}
@proceedings{book3,
editor = {Edward Editor},
title = {Book Three},
year = 2020,
isbn = {123-456-789},
note = {ISBN only},
}
@inproceedings{article4,
author = {Sally Scribe},
title = {Article Four},
doi = {10:1000/4040},
crossref = {book3},
note = {DOI from article, ISBN from crossref should not be displayed},
}
@inproceedings{article5,
author = {Walter Writer},
title = {Article Five},
crossref = {book3},
note = {ISBN from crossref should be displayed},
}
\end{filecontents}
\begin{document}
\nocite{book1,book2,book3,article4,article5}
\printbibliography
\end{document}
如何调整 Andrew 的答案,使其能够考虑交叉引用条目中的isbn
和doi
字段?或者如果失败了,是否有其他解决方案(无需手动编辑参考书目条目)可以实现此目的?
答案1
Sourcemap 在解析过程中的执行时间相当早,.bib
远早于字段别名和数据继承应用之前。这意味着您的 Sourcemap 根本不知道某个条目是否会继承某个字段。
最好仅在biblatex
所有数据可用时才隐藏该字段。概念上最好的方法可能是通过\AtDataInput
,但它需要一个新的辅助宏。
\documentclass{article}
\usepackage[backend=biber]{biblatex}
\makeatletter
\newcommand*{\ClearFieldAtDataInput}[1]{%
\csxappto\blx@bbl@data{%
\undef\expandafter\noexpand\csname abx@field@#1\endcsname}}
\makeatother
\AtDataInput{%
\iffieldundef{doi}
{}
{\ClearFieldAtDataInput{isbn}}}
\begin{filecontents}{\jobname.bib}
@proceedings{book1,
editor = {Adam Author},
title = {Book One},
year = 2020,
doi = {10.1000/1010},
note = {DOI only},
}
@proceedings{book2,
editor = {Betty Bookwriter},
title = {Book Two},
year = 2020,
doi = {10.1000/2020},
isbn = {123-456-789},
note = {DOI and ISBN; ISBN should not be displayed},
}
@proceedings{book3,
editor = {Edward Editor},
title = {Book Three},
year = 2020,
isbn = {123-456-789},
note = {ISBN only},
}
@inproceedings{article4,
author = {Sally Scribe},
title = {Article Four},
doi = {10:1000/4040},
crossref = {book3},
note = {DOI from article, ISBN from crossref should not be displayed},
}
@inproceedings{article5,
author = {Walter Writer},
title = {Article Five},
crossref = {book3},
note = {ISBN from crossref should be displayed},
}
\end{filecontents}
\addbibresource{\jobname.bib}
\begin{document}
\nocite{book1,book2,book3,article4,article5}
\printbibliography
\end{document}
或者,你可以使用标准\AtEveryBibitem
/\AtEveryCitekey
钩子
\documentclass{article}
\usepackage[backend=biber]{biblatex}
\newcommand*{\clearisbn}{%
\iffieldundef{doi}
{}
{\clearfield{isbn}}}
\AtEveryBibitem{\clearisbn}
\AtEveryCitekey{\clearisbn}
\begin{filecontents}{\jobname.bib}
@proceedings{book1,
editor = {Adam Author},
title = {Book One},
year = 2020,
doi = {10.1000/1010},
note = {DOI only},
}
@proceedings{book2,
editor = {Betty Bookwriter},
title = {Book Two},
year = 2020,
doi = {10.1000/2020},
isbn = {123-456-789},
note = {DOI and ISBN; ISBN should not be displayed},
}
@proceedings{book3,
editor = {Edward Editor},
title = {Book Three},
year = 2020,
isbn = {123-456-789},
note = {ISBN only},
}
@inproceedings{article4,
author = {Sally Scribe},
title = {Article Four},
doi = {10:1000/4040},
crossref = {book3},
note = {DOI from article, ISBN from crossref should not be displayed},
}
@inproceedings{article5,
author = {Walter Writer},
title = {Article Five},
crossref = {book3},
note = {ISBN from crossref should be displayed},
}
\end{filecontents}
\addbibresource{\jobname.bib}
\begin{document}
\nocite{book1,book2,book3,article4,article5}
\printbibliography
\end{document}