在 LaTeX 中经常使用元数据,最常见的是:
- \标题
- \作者
- \日期
- \地址
大部分情况下无需有效性检查即可使用。
是否有一个包可以允许人们定义元数据的其他条目并使用文档中的值,并可能定义测试并检查条目的值?
看起来这样的包对于扩展元数据的使用极其有用,允许定义内部和外部数据的层次结构,从而允许进行测试。
答案1
正如评论中提到的,这个问题相当不明确。但是,编写元数据的“测试套件”相对容易。命令\title
等\author
将其参数写入内部宏等\@title
。\@author
例如,您可以使用正则表达式检查这些内部宏的值。虽然这绝不是执行此类检查的最佳或最简单的方法,但它可以作为概念证明。
但请注意,一般情况下,这些字段中的大多数输入都是允许的。对于下面的玩具示例,我定义了一些规则,但对于他们每个人来说,很容易想象出一种打破规则是合理的情况。我认为这不是我的玩具规则本身的限制,因为任何你能想出的规则都有例外。
现在来看看代码。首先,它定义了\address
与 类似的命令\title
(即,将参数存储在 中\@address
),因为这个命令在类中没有默认定义article
。
然后它设置一些在检查期间显示的消息。之后将内部宏复制到标记列表中并用作正则表达式的输入。
代码的其余部分是一般的管理内容:由于某种原因\regex_match
不接受令牌列表多变的但直接只显示一个标记列表,因此需要创建一个变体。我尝试将包代码和用户命令分开,并将所有内容放在一个.sty
文件中。
文件metadatacheck.sty
:
\ProvidesPackage{metadatacheck}[2024/01/07 v0.1 Regex Check on Metadata]
\newcommand{\address}[1]{\gdef\@address{#1}}
\ExplSyntaxOn
\prg_generate_conditional_variant:Nnn \regex_match:nn {nV} {T,F,TF}
\msg_new:nnnn{metadatacheck}{titleok}{Title~check~OK}{}
\msg_new:nnnn{metadatacheck}{authorok}{Author~check~OK}{}
\msg_new:nnnn{metadatacheck}{dateok}{Date~check~OK}{}
\msg_new:nnnn{metadatacheck}{addressok}{Address~check~OK}{}
\msg_new:nnnn{metadatacheck}{titleerr}{Title~does~not~start~with~upper~case}{}
\msg_new:nnnn{metadatacheck}{authorerr}{Author~cannot~have~numbers}{}
\msg_new:nnnn{metadatacheck}{dateerr}{Date~does~not~include~4-digit~year}{}
\msg_new:nnnn{metadatacheck}{addresserr}{Address~too~short~(5~characters~minimum)}{}
\cs_new:Nn \check_meta_data: {
\tl_set:Nx \l_title_tl {\@title}
\tl_set:Nx \l_author_tl {\@author}
\tl_set:Nx \l_date_tl {\@date}
\tl_set:Nx \l_address_tl {\@address}
\regex_match:nVTF{\A[A-Z]}{\l_title_tl}{\msg_note:nn{metadatacheck}{titleok}}{\msg_warning:nn{metadatacheck}{titleerr}}
\regex_match:nVTF{\A[^0-9]+\Z}{\l_author_tl}{\msg_note:nn{metadatacheck}{authorok}}{\msg_warning:nn{metadatacheck}{authorerr}}
\regex_match:nVTF{\d{4}}{\l_date_tl}{\msg_note:nn{metadatacheck}{dateok}}{\msg_warning:nn{metadatacheck}{dateerr}}
\regex_match:nVTF{.{5}}{\l_address_tl}{\msg_note:nn{metadatacheck}{addressok}}{\msg_warning:nn{metadatacheck}{addresserr}}
}
\NewDocumentCommand{\CheckMetaData}{ }
{
\check_meta_data:
}
\ExplSyntaxOff
用户文档:
\documentclass{article}
\usepackage{metadatacheck}
\title{my Title}
\author{Alic3 Sm1th}
\date{Christmas '23}
\address{23 Mulholland Drive}
\CheckMetaData
\begin{document}
\maketitle
\end{document}
结果(在终端和日志文件中):
Package metadatacheck Warning: Title does not start with upper case
Package metadatacheck Warning: Author cannot have numbers
Package metadatacheck Warning: Date does not include 4-digit year
Package metadatacheck Info: Address check OK
当然,可以通过允许用户提供正则表达式和消息(通过文档命令或者配置文件)来进一步扩展。
答案2
目前 ctan 上至少有一个由 Scott Pakin 开发的软件包https://ctan.org/pkg/hyperxmp?lang=en 超XMP可以完成 OP 所要求的事情,如果需要扩展的话,这将是一个很好的起点。
在评论中,有人建议在进行任何开发工作之前先编写规范。我还提供了 Adobe 规范的链接,我认为这是一个很好的例子。在许多情况下,只需使用枚举列表和表格即可。我认为最重要的部分是程序的范围。在问题的背景下,它必须回答,鉴于元数据是不同程序之间交换信息的接口,预计哪些软件可以读取这些信息。编写规范后,就可以开发验证功能。应注意在必要时涵盖不同的书写系统和编码。
符合 LaTeX 软件包要求的日期数据验证示例可在 l3doc 列表中找到,该示例使用 l3 编程层编写。l3 编程杂技的奇迹!
需要提醒的是,Web 开发也经历了类似的发展阶段,但是这种本体未能真正流行起来,因为搜索变得越来越好,现在有了 LLM,它们可能会一起消失,但这只是我的观点,并不意味着要打击你。
答案3
这并非确切的答案,而是 Ulrike Fischer 在上面的评论中提出的规格。它仍处于萌芽状态,我们将对其进行相应的编辑。
包元数据将定义并允许使用和验证元数据条目。
要定义新条目,请使用:
\definemetadataentry[type=
format=yyyy-mm-dd,
lower_range=0001-01-01,
upper_range=9999-12-31,
finite_range=,
default_value=,
optional/required,
validation_routine=,
hierarchy=
]{name_of_metadata_entry}
在哪里:
(数据类型):
可:
- 数字(整数或小数)
- 字符串
- 约会时间
格式:
提供刚刚定义的数据类型的格式。
下限=0001-01-01:
上限范围=9999-12-31:
定义连续或太长而无法完整列出的数据的下限和上限范围。
日期设置范围示例:0001-01-01 至 9999-12-31
有限范围:
定义可以轻松完整列出的数据范围。
默认值:
如果未定义,则元数据条目的默认值。
可选/必需:
定义特定元数据条目在定义它的范围内是否是必需的还是可选的。
验证程序(外部):
调用外部例程来验证输入。
等级制度:
根据另一个先前定义的元数据条目递归定义的元素。
定义和使用示例
数据类型:
有三种类型的数据需要考虑:
- 数字(整数或小数)
- 字符串
- 约会时间
日期格式:
日期:格式:YYYY-MM-DD 日期时间:格式:YYYY-MM-DD HH:MI:SS
日期格式可以是不同类型,例如:“dd-mm-yyyy”、“yyyy-mm-dd”、“mm-dd-yyyy”。
提及 10 种最常用的格式,包括短世纪(yy)和长世纪(yyyy)。
- 美国:mm/dd/yy & mm/dd/yyyy
- ANSI:yy.mm.dd 和 yyyy.mm.dd
- 英国/法国:dd/mm/yy & dd/mm/yyyy
- 德语:dd.mm.yy & dd.mm.yyyy
- 日本:yy/mm/dd 和 yyyy/mm/dd
- ISO:yymmdd & yyyymmdd
- 欧洲默认 + 毫秒:dd mon yyyy hh:mi:ss:mmm (24h)
- 回历:dd/mm/yyyy hh:mi:ss:mmmAM
RequirePackage{metadata}
\definemetadataentry[type=DATETIME,
format=yyyy-mm-dd,
lower_range=0001-01-01,
upper_range=9999-12-31
default_value=2000-12-31,
optional,
validation_routine=/usr/local/texlive2024/bin/abc.lua,
]{date_of_publication}
\definemetadataentry[type=DECIMAL,
fomat=(8,6),
]{latitude}
\definemetadataentry[type=DECIMAL,
format=(9,6),
]{llongitude}
\definemetadataentry[type=CHARACTERSTRING]{email}
\definemetadataentry[type=CHARACTERSTRING]{url}
\definemetadataentry[type=NUMERIC,
format=integer,
lower-range=1,
upper-range=9999,
]{volume_number}
\definemetadataentry[type=CHARACTERSTRING(2),
range={US,MX,CA,GT,HT,CU,HN,...},
]{north_american_country}
元数据的层次结构。
\definemetadataentry[type=CHARACTERSTRING(2),
required,
]{country}
\definemetadataentry[type=CHARACTERSTRING(10),
hierarchy=country,
]{zipcode}
使用示例:
\zipcode[BR]{22430-085}
\zipcode[US]{91106-3840}
\zipcode[CA]{K1A 0T6}
\zipcode[DE]{13057}
\zipcode[IR]{81599-95950}
\definemetadataentry[type=CHARACTERSTRING(2),
required,
]{decade}
\definemetadataentry[type=CHARACTERSTRING(10),
hierarchy=decade,
]{msc}
使用示例:
\msc[2010]{76B75}
\msc[2020]{76D55}
\definemetadataentry[type=CHARACTERSTRING(100),
required,
]{full_name}
\definemetadataentry[type=CHARACTERSTRING(30),
hierarchy=full_name,
]{last_name}
使用示例:
\full_name{John Ewing}
\last_name{Ewing}