Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

图、表格、数据集描述与 Research Object 投影

PurRDF 把 RDF 1.2 数据集投影为图、表格、数据集描述与 Research Object 格式,而不让其中任何一种格式成为语义权威。一个 Rust 引擎实现该映射,把其工件打包为规范的 USTAR,并原样通过 Rust、CLI、Python、WebAssembly 与 C 对外提供。

每项操作都具有四条不可妥协的性质:

  • 配置提供每一个词汇角色、标识 IRI、处理策略与资源上限;库不捏造其中任何一项;
  • 对同一数据集与配置,输出字节是确定性的;
  • 损失总是被计算为一份封闭的、带位置的台账,即使宿主选择不显示它;
  • 格式错误、有歧义、非规范或越界的输入都是硬错误。

Profile

Profile原生工件方向RDF 保真度
lpg-csv通用的节点/边 CSVRDF ↔ 载体精确的 RDF 边带(sideband);属性图降级记入台账
neo4j-csvNeo4j Admin Import CSVRDF ↔ 载体同一规范 LPG 权威与台账
open-cypher确定性的 CREATE 程序RDF ↔ 载体严格的读取器恰好接受所输出的语法
graphmlGraphML 1.0 XMLRDF ↔ 载体精确的 RDF 边带;严格的命名空间/键验证
csvw-exactCSVW 元数据加 RDF 1.2 表RDF ↔ 载体无损
csvw-termsCSVW 元数据加调用方声明的实体表RDF → 视图带位置的封闭损失台账
okf-termsOKF v0.1 概念文档与索引RDF → 视图带位置的封闭损失台账
obo-graphsOBO Graphs 0.3.2 JSONRDF → 视图带位置的封闭损失台账
skosSKOS TurtleRDF → 视图带位置的封闭损失台账
croissant-1.1croissant.jsonRDF ↔ 载体共享模型;profile 损失带位置
ro-crate-1.3ro-crate-metadata.jsonRDF ↔ 载体共享模型;profile 损失带位置
datacite-4.6datacite.xmlRDF ↔ 载体共享模型;profile 损失带位置
dcat-3dcat.jsonldRDF ↔ 载体共享模型;profile 损失带位置
dcat-rdfdcat.<native extension>RDF → 视图映射生成或由调用方 CONSTRUCT 生成;不含空节点的 RDF
voidvoid.<native extension>RDF → 视图所选图的统计信息、分区与链接集
frictionless-data-package-1datapackage.jsonRDF ↔ 载体共享模型;profile 损失带位置

ProjectionProfile 与 LiftProfile 的类型区分很重要:经整理的 CSVW/OKF 术语、OBO Graphs、SKOS、原生 DCAT RDF 与 VoID 甚至无法被指名为 lift profile(提升 profile)。它们是有用的视图,而不是冒充的交换格式。

单一的规范 LPG 模型

四种带标签属性图语法是同一个带类型 LPG 模型之上的适配器,而不是各自独立的 RDF 映射。节点、边、标签、带类型的属性原子、图上下文、具体化节点、注解与精确的 RDF 陈述只排序、验证一次。这使四种载体拥有相同的标识与反向映射。

属性图并不定义 RDF 语义。因此,PurRDF 把每一次语义降级都记入 RDF-to-LPG 台账,尽管规范包同时也保留了用于重建的精确 RDF 边带。载体的使用方可以使用原生 LPG 视图;对 RDF 提升而言,边带仍是权威。

读取器接受 PurRDF 输出的完整形式,并拒绝任何漂移:错误的表头、重复的行或键、悬空的端点、token 映射不一致、未知的 Cypher 语句、不安全的 XML、意外的包成员以及非规范编码都会失败。

LPG 范围、上限、进度与内存

每个 LPG 配置都包含一个必需的 scope。{"mode":"all"} 是请求所有图与谓词的唯一方式;省略绝不意味着「全部」。选择性范围分别独立控制默认图、精确的命名图项、谓词允许/拒绝集合、节点的 RDF 类型以及原生边谓词。命名的空节点图保留其范围序号,每个选择器 IRI 都必须是绝对 IRI。

选择是一个封闭的 RDF 1.2 操作。即使该谓词在输出中被省略,节点类型也依据经图选择后的 rdf_type 陈述建立索引。保留的边会保留其端点。具体化节点与注解仅在其源陈述保留下来时才被保留,且注解谓词遵循同一个谓词选择器。这些规则防止所选属性图包含悬空的边带。

LpgExecutionLimits 分别独立限制扫描的输入记录、模型记录、节点与边的数量。ProjectionLimits 限制工件数量、单个工件字节数、工件正文总字节数、规范 USTAR 字节数以及递归 RDF 项的深度。每个上限都在相应的模型变更或接收器(sink)写入之前被消耗;第一次超出即为带类型的硬错误。引擎不做分页。拆分一个按规范排序、可精确逆转的载体,会使页面标识与跨页端点依赖顺序;调用方应改为选择更窄的范围或更大的显式上限。

直接接收器(sink)路径会保留所选的规范 LPG 模型,因为稳定的、与后端无关的排序、类型选择、端点闭合以及精确的 RDF 边带都需要这份有界的排序/索引。随后,它按词法路径顺序输出每个工件,每块不超过 16 KiB,既不保留完整的工件正文,也不保留 USTAR 缓冲区。归档便捷路径则额外保留物化后的工件与最终归档。因此,接收器路径的内存以所选模型加编码器临时空间与一个分块为界;它并不是一个常量内存的 RDF-to-LPG 映射器。

进度观察者接收单调的 scanning、building、writing、complete 或 aborted 快照,其中含输入/模型/节点/边、已完成工件、正文字节与当前路径计数器。接收器(sink)或观察者的失败会中止当前事务。接收器必须暂存部分状态,仅在 commit_package 时发布,并在 abort_package 时丢弃。

CSVW

较底层的 CSVW API 对带注解的表组、模式、方言、列、行、继承属性、数据类型与格式、语言与文本方向、空值/默认值/分隔符处理、虚拟列或被抑制的列、主键与外键、行标题、注解以及 URI 模板进行建模。它在一个完整的内存包上支持标准的 CSVW CSV-to-RDF 处理模式;文件系统与网络发现仍由调用方负责。

csvw-exact 归档 profile 使用这套机制无损地承载 RDF 1.2。其规范表保留项、四元组、命名图归属、递归三元组项、具体化节点绑定、注解、数据类型、语言、方向以及空节点作用域。一次有效的精确往返(转换)的台账为空。

独立的 csvw-terms profile 是一个刻意整理的宽表视图,面向类、属性、个体、业务实体或发布清单这类紧凑目录。这些名称不带任何内置含义:每张表、每个选择器、谓词、数据类型与标识规则都由调用方提供。该 profile 从不导入本体模型,也不假定 RDF、RDFS、OWL 或任何应用词汇表。

CsvwTermsConfig 只包含必需的策略:

  • csvw 是完整的规范性 CSVW 上下文、词汇表、处理模式、记录上限与包上限;
  • metadata_path 是安全的、相对于包的元数据成员;
  • graph_selection 要么是显式的 all,要么是一个精确的默认图标志加一组命名图 IRI;
  • 每条有序的表声明都提供稳定的名称、绝对表 URL、工件路径、行选择器、可见的主语 IRI 列,以及一个或多个有序的谓词列;
  • 选择器可以通过一个显式指名的类型谓词约束任意/全部/无 RDF 类型,也可以约束主语 IRI 前缀;类型谓词恰好在类型集合非空时出现,而空的前缀集合表示不约束主语命名空间;
  • 谓词列接受精确的 IRI 宾语,或带有精确数据类型、语言与 RDF 1.2 方向刻面的字面量,另加是否必需以及显式的单值或多值基数;
  • execution_limits 限制输出总行数、所表示的值的数量以及单个单元格中的值的数量,与包上限和输入记录上限相互独立。

表之间的重叠是有意为之。一个主语匹配多个选择器时,可以出现在多个视图中。重复的表标识、路径、列名或被映射的谓词都会被拒绝。One 遇到第二个匹配值即失败。Many 按规范顺序对 RDF 项排序,并用调用方的分隔符连接;若实际值中含有该分隔符,则失败,而不是生成一个有歧义的单元格。RDF 的直接值陈述不带源序列,因此该 profile 不捏造 CSVW 的有序列表语义。

行按主语 IRI 排序,值按规范的 RDF 项顺序排序,列与表按其声明顺序排序,归档成员按词法路径排序。因此,无论源数据的驻留顺序或陈述的插入顺序如何,同一数据集与配置都会产生相同的 CSV、元数据与 USTAR 字节。

每一行源数据都有着落。未被选择的图或主语、空节点或三元组项主语、未映射的谓词、刻面不匹配的宾语、所选的命名图归属、空的命名图、具体化节点绑定与注解,都会产生稳定的、带源位置的台账条目。生成的表本身可以用规范性的 read_csvw API 读取,但无法重建被省略的源 RDF。RDF 1.2 方向在带注解的 CSVW 值与 textDirection 元数据中仍保持精确;W3C 的 CSVW-to-RDF 算法本身以 RDF 1.1 为目标,因此返回不带方向的语言字面量。所以 csvw-terms 没有对应的 LiftProfile 变体,也不含隐藏的精确边带;凡需要归档保真度或 RDF 往返(转换)时,请使用 csvw-exact。

Research Object 载体

Croissant 1.1、RO-Crate 1.3、DataCite Metadata Schema 4.6、DCAT 3 与 Frictionless Data Package v1 都是同一个带类型的 ResearchObjectModel 之上的适配器。该模型涵盖数据集的标识与描述、标识符与日期、行为主体、许可证、资源与校验和、活动、记录集以及字段。它是 N 对 N 的语义枢纽:一份文档可以被提升为采用调用方词汇表的 RDF,再投影为任何其他 profile,而无需为每对格式单独实现。

这三个 JSON-LD profile 完全离线。Croissant、RO-Crate 与 DCAT 的配置既提供精确的、被接受/被输出的 @context JSON,也提供完整的术语到绝对 IRI 的定义映射。PurRDF 从不解引用上下文 URL、从不跟随 @import,也从不提供词汇表。展开后的图通过其他地方同样使用的原生 RDF 1.2 JSON-LD 引擎进行验证。

RO-Crate 还要求显式的 packaging 值。metadata-only 是单一描述符形式。attached 接受一个有界的 RoCrateAssets 载荷载体,生成 ro-crate-metadata.json、一个自包含的确定性 ro-crate-preview.html 以及被引用的载荷成员。引擎本身不访问文件系统:Rust 接收 RoCrateAssets,CLI 通过 --assets 接收一个仅含载荷的规范 USTAR,语言绑定接收同样的归档字节。本地 File 标识与载荷路径必须一一对应;缺失/多余的资产、保留路径、重复归属、声明大小不符,或非标准的 attached crate 根,都是完整性错误。读取器验证同一契约以及精确的预览渲染。预览文件不会被加入 hasPart;只有载荷 File 实体才是根数据实体。

DataCite 配置提供命名空间、模式位置、XML-Schema-instance IRI、受控值以及常用 RDF 角色。其读取器能识别命名空间,并拒绝 DTD/实体输入。存在单独的标识符时即使用它;否则以必需的调用方/文档数据集标识作为主标识符,因此不会合成任何 DOI。Frictionless 配置提供精确的包 profile 与包名。没有单独定位符的资源使用其受调用方约束的相对实体标识作为安全的 Data Package 路径;不会生成新的 IRI。

每个原生读取器都接受 PurRDF 输出的完整 profile 形式,并拒绝重复成员、悬空引用、不安全的相对路径、错误的上下文/profile 标识、有歧义的基数以及超出资源上限的输入。共享模型之外的格式特有构造,由稳定的、带位置的台账条目表示。已提交的对抗性测试夹具为每个 profile 都覆盖了非空的反向台账;一个 5×5 的蜕变矩阵证明共享的语义交集经过每一对源/目标都保持稳定。

原生 RDF 数据集描述

dcat-3 仍是上文所述的双向 JSON-LD Research Object 载体。独立的 dcat-rdf profile 以任一已注册的原生 RDF 语法输出一个不含空节点的默认图。其带标签的 source 是必需的,有两种显式模式:

  • mapped 复用调用方配置的 Research Object 解释,然后以调用方完整的 DCAT 上下文/角色映射,外加显式的 rdf:type 与 XSD 字符串 IRI,输出直接的 RDF IR。共享模型中的语义降级台账被保留。
  • construct 把调用方提供的一个 SPARQL CONSTRUCT 视为完整的视图。查询字节、输入记录、输出记录、项深度、工件、正文与归档字节全部有界。查询在配置时即被解析,在包括 RDF 1.2 陈述层在内的完整数据集上运行,且必须产生一个图。

两种模式使用同一个确定性的原生序列化器。所选语法决定唯一的 dcat.<extension> 成员;配置从不推断词汇表、查询、语法或基准 IRI。由于结果是描述视图而非精确载体,dcat-rdf 没有 lift profile。

void profile 直接以采用调用方词汇表的 RDF 生成一份确定性的、不含空节点的数据集描述。其配置指名被描述的数据集、用于生成稳定资源 IRI 的基准、源头部的主语与谓词、三个互不相同的头部/对齐/元数据图选择器、一个非空的精确数据图集合、全部 22 个目标角色、本地与外部数据集前缀注册表、可选的元数据链接映射与静态数据集陈述,以及每一项包/执行上限。

统计信息只依据所选的数据图计算。triples 统计所选陈述数,entities 与 distinctSubjects 统计不同主语数,distinctObjects 统计不同宾语数,classes 统计所配置类型谓词的 IRI 宾语数,properties 统计谓词数。类分区包含主语具有该类的每条所选陈述;属性分区包含谓词恰为该谓词的陈述。分区与链接集 IRI 使用位于调用方基准之下的完整确定性标识符。

对齐行必须具有 IRI 端点。最长前缀匹配对每个端点分类,等长歧义或无匹配都是错误,且每条对齐至少要有一个本地端点。链接集保留主语/宾语方向,并按主语数据集、宾语数据集与谓词分组。生成器从不猜测归属、从不交换方向、从不获取元数据,也从不提供 VoID/RDF/XSD 命名空间。

完整的、可移植的 example.org 配置与一个可执行的 TriG 源位于 crates/rdf/tests/fixtures/dataset-description/ 下。它们原样运行于每个宿主,例如:

purrdf project --profile dcat-rdf \
  --config crates/rdf/tests/fixtures/dataset-description/dcat-rdf.json \
  --from trig crates/rdf/tests/fixtures/dataset-description/void-source.trig dcat.tar

purrdf project --profile void \
  --config crates/rdf/tests/fixtures/dataset-description/void.json \
  --from trig crates/rdf/tests/fixtures/dataset-description/void-source.trig void.tar

OBO Graphs 与 SKOS 视图

OBO Graphs 写出器输出 0.3.2 版的节点、边与元数据,外加可直接表示的等价节点集、逻辑定义、限制、定义域/值域公理以及属性链。调用方提供图标识以及每一个 RDF/RDFS/OWL/OBO 角色。输出依据固定版本的官方 0.3.2 JSON Schema 进行检查。

SKOS 写出器把调用方选定的 RDF 图映射到一个由调用方标识的概念体系中。它支持概念、标签、记号、文档、层级、映射关系、成员关系与顶层概念,同时执行相关的 SKOS 完整性条件。目标 SKOS 角色 IRI 与源角色一样由调用方提供;PurRDF 是载体,连标准词汇表的默认值都不生成。

两种视图都以稳定的源位置记录每一个被省略或被放宽的源构造、命名图归属以及 RDF 1.2 陈述层行。

配置

生产用归档 API 接受 {"profile":"…","config":{…}} 形式的严格带标签 JSON。未知字段以及 profile/config 不匹配都会失败。不存在默认配置。一个最小的通用 LPG 示例如下:

{
  "profile": "lpg-csv",
  "config": {
    "rdf_type": "https://example.org/type",
    "scope": {"mode": "all"},
    "limits": {
      "max_artifacts": 16,
      "max_artifact_bytes": 1000000,
      "max_total_bytes": 4000000,
      "max_archive_bytes": 5000000,
      "max_term_depth": 16
    },
    "execution_limits": {
      "max_input_records": 1000,
      "max_model_records": 1000,
      "max_nodes": 1000,
      "max_edges": 1000
    }
  }
}

若要只保留一个命名图,同时接纳所有谓词与类型,可把 scope 对象替换为:

{
  "mode": "select",
  "include_default_graph": false,
  "named_graphs": {
    "mode": "only",
    "include": [{"kind": "iri", "value": "https://example.org/business"}],
    "exclude": []
  },
  "predicates": {"mode": "all", "deny": []},
  "node_types": {"mode": "all", "deny": []},
  "edge_types": {"mode": "all", "deny": []}
}

包上限与规范模型上限在写入与读取时按需适用;输入记录上限约束 RDF 投影扫描。它们合起来覆盖成员数量、单个成员字节数、正文总字节数、编码后的归档字节数、输入/模型记录数、节点数、边数以及递归 RDF 项深度。它们属于信任边界策略,必须由应用程序选定。

Research Object 配置额外包含一个必需的 common 对象,其中含完整的 roles、identity 以及有界的 policy 映射。各 profile 特有的词汇角色、上下文数据、模式标识、受控值以及原生 profile 标识同样是必需的。全部五个 profile 的完整可运行 example.org 配置位于 crates/rdf/tests/fixtures/research-objects/carrier/ 下;它们是示例,绝非库的默认值。

经整理的 CSVW 的完整严格带标签 JSON 结构由 crates/rdf/tests/fixtures/csvw-terms.json 覆盖测试。其图选择器是显式的:

{
  "kind": "include",
  "default_graph": true,
  "named_graphs": ["https://example.org/business"]
}

随后,每个表选择器指名其自身的调用方词汇与行集合:

{
  "type_predicate": "https://example.org/type",
  "any_types": ["https://example.org/Class"],
  "all_types": [],
  "none_types": ["https://example.org/Retired"],
  "iri_prefixes": ["https://example.org/vocab/"]
}

可运行的 csvw_terms Rust 示例用三条普通的表声明——类、属性与个体——构造完整配置,并写出规范归档:

cargo run -p purrdf-rdf --example csvw_terms -- /tmp/terms.tar

独立的 okf-terms profile 把由调用方分类的 RDF 资源投影为 OKF v0.1 概念文档与导航索引。配置就是整个投影代数:图范围、类别选择器、安全的路径标识、固定的标准字段角色、生产者扩展、正文/链接小节、索引正文、带内保真度声明以及资源上限。没有任何词汇或类别带有由库赋予的含义。概念 frontmatter 使用 OKF 标准键顺序,随后是按词法排序的扩展键;保留的 index.md 文件包含导航用 Markdown,不含概念 frontmatter。

完整的严格可移植配置是 crates/rdf/tests/fixtures/okf-terms.json。Rust、CLI、Python、WebAssembly/TypeScript 与 C 都原样接受它:

purrdf project --profile okf-terms --config okf-terms.json \
  --from trig ontology.trig knowledge.tar

该 profile 被有意排除在 LiftProfile 之外。从 bundle 到 RDF 的导入仍由现有的、由调用方配置 profile 的 OKF 编解码器负责;经整理的生成器会记录它未承载的每一行源数据,而不是声称存在逆映射。

Rust 归档 API

#![allow(unused)]
fn main() {
use purrdf::{
    LiftProfile, LpgConfig, LpgExecutionLimits, LpgScope, ProjectionConfig,
    ProjectionLimits, ProjectionProfile, lift_archive, parse_dataset,
    project_archive, datasets_isomorphic,
};

let dataset = parse_dataset(
    b"<https://example.org/alice> <https://example.org/knows> <https://example.org/bob> .",
    "text/turtle",
    None,
)?;
let limits = ProjectionLimits::new(16, 1_000_000, 4_000_000, 5_000_000, 16)?;
let config = ProjectionConfig::LpgCsv(LpgConfig::new(
    "https://example.org/type",
    LpgScope::all(),
    limits,
    LpgExecutionLimits::new(1_000, 1_000, 1_000, 1_000)?,
)?);

let package = project_archive(dataset.as_ref(), ProjectionProfile::LpgCsv, &config)?;
let lifted = lift_archive(&package.archive, LiftProfile::LpgCsv, &config)?;
assert_eq!(lifted.dataset.quad_count(), 1);
assert!(datasets_isomorphic(&dataset, &lifted.dataset));
Ok::<(), Box<dyn std::error::Error>>(())
}

ProjectionArchive 包含 profile、USTAR 字节与损失台账。ProjectionLift 包含重建出的不可变数据集及其提升台账。project_lpg_artifacts_to_sink 通过同一套配置与映射引擎,把四个 LPG profile 分派到调用方持有的 ProjectionArtifactSink 中;LpgProgressObserver 提供结构化的进度。更底层的 API 还公开带类型的 LPG、CSVW、OBO、SKOS、DCAT RDF、VoID 以及内存中的 Research Object/工件模型。

其他生产接口

各接口的名称遵循同一个 profile/config/archive 契约:

宿主物化投影Attached RO-Crate直接 LPG 工件提升(lift)
Rustproject_archiveproject_archive_with_assetsproject_lpg_artifacts_to_sinklift_archive
CLIpurrdf projectpurrdf project --assets PAYLOADS.tar—purrdf lift
Pythonpurrdf.project(...)purrdf.project(..., assets=archive)purrdf.project_artifacts(...)purrdf.lift(...)
JavaScriptdataset.project(...)dataset.projectWithAssets(...)—liftProjection(...)
Cpurrdf_project(...)purrdf_project_with_assets(...)—purrdf_lift(...)

可运行的示例位于:

  • crates/rdf/examples/projection_archive.rs
  • crates/rdf/examples/csvw_terms.rs
  • crates/rdf/examples/okf_terms.rs
  • crates/rdf/examples/research_object_roundtrip.rs
  • crates/rdf/examples/attached_ro_crate.rs
  • crates/cli/examples/projection-roundtrip.sh
  • crates/cli/examples/dataset-descriptions.sh
  • bindings/python/examples/projection_roundtrip.py
  • bindings/python/examples/projection_stream.py
  • crates/rdf-wasm/js/examples/projection-roundtrip.mjs
  • crates/rdf-capi/examples/projection_roundtrip.c

确定性与验证

归档成员使用按词法排序的安全 POSIX 相对路径。USTAR 头、元数据、校验和、填充与结尾块都是固定的。读取器验证归档,并要求其规范重编码与输入字节一致,因此不会静默地把攻击者控制的替代形式规范化。

固定版本的 W3C CSVW 清单覆盖 270 个 RDF 用例与 282 个验证用例。一个锁定版本的独立 csvw 实现验证生产输出,并拒绝刻意构造的元数据/数据损坏。OBO 写出器依据固定版本的官方模式独立验证,并配有损坏探针。运行整个投影验证切片:

make projection-oracles
cargo bench -p purrdf-rdf --bench projections -- --quick

该基准测试仅供报告。它测量 RDF-to-LPG 映射、在 20 个图的载体上按范围映射与显式 all 映射的对比、每种 LPG 语法的物化包输出与直接接收器(sink)输出的对比、每条 LPG 读取路径、精确 CSVW 写入/读取、在同一个 12,000 个四元组的载体上精确 CSVW 与经整理 CSVW 的对比、单图与全图的经整理范围对比、OBO Graphs 与 SKOS 投影、映射式与 CONSTRUCT 式 DCAT RDF、VoID 生成、共享的 Research Object 模型,以及全部五条 Research Object 写入/读取路径。它还报告在确定性测试夹具上观察到的内存分配与工件正文大小。