Copyright © 2025-2026 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
本文档定义了 SHACL 规则。
SHACL,即形状约束语言,是一种用于描述 RDF 图结构的语言。 SHACL 可用于多种目的,例如验证、推理、 领域建模、生成本体以告知其他代理、构建用户 界面、生成代码以及集成数据。
SHACL 规则通过根据一组规则与一个基础数据图的组合生成新的 RDF 数据, 来提供推理能力。规则可以表示为 RDF, 或表示为形状规则语言(SRL)。
本规范由 数据形状工作组发布。
本节描述本文档在发布时的状态。 当前 W3C 出版物列表以及本技术报告的最新修订版本可在 W3C 标准与草案 索引中找到。
本文档由 数据形状工作 组作为 工作草案发布,并使用 推荐标准 轨道。
作为 工作草案发布并不意味着 W3C 及其成员的认可。
这是一份草案文档,可能会随时被其他文档 更新、取代或废弃。除作为 进行中的工作之外,不宜引用本文档。 对这一即将成为推荐标准的文档的未来更新可能会纳入 新特性。
本文档由一个依据 W3C 专利 政策运作的工作组 生成。 W3C 维护一份 与该组交付成果相关的任何专利 披露的公开列表; 该页面还包括 披露专利的说明。实际 知晓某项专利且认为该专利包含 必要权利要求 的个人,必须根据 W3C 专利政策第 6 节披露该信息。
本文档受 2025 年 8 月 18 日 W3C 流程文档管辖。
本规范是 SHACL 1.2 规范系列的一部分。有关这些规范的更详细 介绍,请参见 SHACL 1.2 概述。
这些规范如下:
工作草案:
工作组说明草案:
实现者可以通过成功通过 SHACL 1.2 测试套件 的测试用例,部分检查其与上述规范的一致性级别。 但是请注意,通过测试套件中的所有测试并不意味着完全符合这些 规范。 它仅意味着该实现符合测试套件所测试的方面。
本文档介绍 SHACL 1.2 的推理规则,这是一种通过声明式规则 从现有 RDF 数据中派生新的 RDF 三元组的机制。 本文档定义基于规则的推理的语法和语义。
SHACL 规则的实现提供两种操作。 infer 操作将规则应用于给定的 基础图,并生成一个包含通过 执行规则派生出的 RDF 三元组的推理图。 是否将推理图与基础图合并是可选的,并 留给用户决定。query 操作用于确定某个 给定目标模式是否可以使用这些规则从基础图派生出来。
SHACL 规则允许使用新的 RDF 术语,包括空白节点, 这些术语可用于规则头部的三元组模板。
SHACL 规则还支持一些构造,例如失败即否定, 这些构造可能会因规则执行顺序不同而导致不同的推理图。 为避免这种情况,规则使用 分层技术进行求值,该技术在规则之间建立单一的隐式顺序, 确保始终生成相同的推理图。
以下其他规范提供了本文档中使用的基础术语:
本文档中的一些示例使用 RDF 1.2 Turtle [RDF12-TURTLE]。
在本文档中,使用以下命名空间前缀绑定:
| 前缀 | 命名空间 |
|---|---|
rdf: |
http://www.w3.org/1999/02/22-rdf-syntax-ns# |
rdfs: |
http://www.w3.org/2000/01/rdf-schema# |
srl: |
http://www.w3.org/ns/shacl-rules# |
xsd: |
http://www.w3.org/2001/XMLSchema# |
sparql: |
http://www.w3.org/ns/sparql# |
ex: |
http://example.com/ |
在整个文档中,将出现包含 Turtle 格式 RDF 图的彩色编码框。 这些 Turtle 文档片段使用上面给出的前缀绑定。
重置。在适当处使用 reSpec 默认外观。
# This box represents rules
# This box represents input data
# This box represents inferred data
除标记为非规范性的章节外,本规范中的所有编写指南、图表、示例和注释均为非规范性内容。除此之外,本规范中的所有内容均为规范性内容。
本文档中的关键词 MUST NOT 和 SHOULD 应按 BCP 14 [RFC2119] [RFC8174] 中所述进行解释,且仅当它们像此处所示那样 全部以大写形式出现时才如此解释。
本规范为以下内容定义一致性标准:
一个符合一致性的
形状规则
语言文档是一个
RDF
字符串,它
符合语法,并从
RuleSet
产生式开始,且符合
7. 形状规则语言
语法中定义的附加约束
本规范未定义 SHACL 规则 处理器如何处理不符合一致性的规则集。
版本标签是一个用于标识形状规则语言的语法和语义 一致性的字符串。
| 版本标签 |
|---|
| "1.2" |
版本声明 SHOULD 在文档的早期给出。
一个形状 规则语言文档中可以出现多个版本指令。 每个指令适用于其后的文档部分, 直到遇到另一个指令或到达文档末尾。
版本标签也可以由
媒体类型的 version
参数给出。在没有当前
版本指令的情况下,会考虑作为媒体类型一部分指定的版本。
本节为非规范性内容。
给定一个基础图和一个规则集,SHACL 规则会推断新的三元组。 求值的输出是一个推理图,其中包含派生出的、 不出现在基础图中的三元组。
每个规则都有一个称为主体的模式,以及一个 称为头部的结果模板。 规则通过查找主体中变量的值来执行, 使主体匹配组合后的基础图以及 到目前为止执行过程中产生的任何推理三元组。 然后使用这些值来实例化规则头部中的 三元组模板,以生成新的推理三元组。
规则会一直执行,直到不再推断出更多三元组; 随着新的推理三元组可用,规则可能会被执行多次。
SHACL 规则执行被定义为:在创建新的 RDF 术语时, 包括新的空白节点,以及在测试某个模式是否不存在时, 规则执行顺序不会导致不同结果。换言之,无论规则执行顺序如何, 都会生成相同的推理图。
SHACL 规则既有 RDF 语法,也有受 SPARQL 1.2 Query Language 启发的人类友好语法。 规则集求值包含与 SPARQL 类似的元素,但在细节上有所不同, 以确保无论规则执行顺序如何,都生成相同的推理图。
在第一个示例中,我们有以下数据图和规则集:
上述规则应用到数据后,将得出结论:
:X 是 :A 和 :B 的 :childOf:
然后我们可以通过添加一个依赖于其他规则产生的
:childOf 三元组的规则,派生 :descendedFrom 关系:
我们可以添加一个依赖于 :descendedFrom 三元组的规则,
以推断 :X 是 :C 的 :descendedFrom:
这会添加三元组 :X :descendedFrom :C。
最后一条规则是一个递归规则,其规则主体 依赖于该规则的头部。
我们可以在规则主体中使用表达式来限制主体匹配中 变量的取值。 例如,给定关于城镇及其人口的数据, 我们可以为人口大于 1500 的城镇推断一个类:
FILTER 对表达式求值;如果表达式求值为 true,
则保留当前的变量绑定集合;如果表达式求值为 false,则丢弃
当前的变量绑定集合。
这与
SPARQL 的 FILTER 操作
相同,并且 SHACL 规则提供了许多与 SPARQL 相同的函数和运算符。
否定允许你指定一个不得匹配的模式。 这称为“失败即否定”。
为了对否定元素求值,规则求值算法会确保 所有可能产生与否定元素中的模式匹配的三元组的规则 都已完成。这称为 分层,并确保否定基于 所有相关的可能三元组,无论这些三元组来自数据, 还是来自其他规则推断出的推理三元组。
赋值允许你将表达式的结果赋给规则主体中的一个变量。 这可用于基于数据创建新的 RDF 术语。
空白节点可以用于规则头部,并且每次规则求值生成三元组时, 每个空白节点都会生成一个新的空白节点。
涉及赋值的规则,以及在其 规则头部中创建空白节点的规则,都是只运行一次规则。 这类规则会在所有可能产生其所依赖数据的规则之后运行, 并在任何依赖其产生数据的规则之前运行。 在规则头部中涉及空白节点的规则也会创建新的 RDF 术语,并且是只运行一次规则。
此条件确保创建 RDF 术语的规则不会多次生成新术语, 从而导致潜在的不同结果;同时也确保此类规则不会 回到自身并造成无限数量的 RDF 术语。
一个 SHACL 规则集可以通过在该规则集的 规则导入中 包含其他规则集的 URL 来纳入其他规则集。 这允许将规则组织成可在规则集之间共享的库。
规则集中的 IMPORTS 语句会在该规则集中任何规则
被求值之前处理。在导入步骤期间,如果被导入的规则集
有自己的导入项,这些导入项也会被递归处理。
在处理规则集时遍历 IMPORTS 语句可能导致
循环导入。一个规则集只会被导入一次;
导入语句图中的循环不会导致无限循环。
数据块允许以简洁方式直接向规则集求值提供 RDF 三元组。 数据块中的三元组会被添加到推理图中,并可用于 规则主体中的匹配。
@@示例待更新
规则被组织为规则集。 规则集和数据图(即基础图)是求值的输入。 输出是一个称为推理图的图, 其中推理出的三元组不出现在数据图中。
在求值期间,根据某条规则推理出的三元组 可用于其他规则中的匹配。 规则集求值会持续进行,直到推理图 包含从规则集和数据图的输入中 可得到的所有可能三元组。
在规则本身求值之前,求值会从两个步骤开始, 以准备规则集:
一旦规则集完成准备,求值就会 按顺序取出分层中的每一层, 将该层中的规则求值至完成, 然后进入下一层。
本节为非规范性内容。
SHACL 规则与 SPARQL 关系密切。SHACL 规则被设计为与 SPARQL 兼容,并且 SHACL 规则中的许多构造都受到 SPARQL 的启发。 但是,也存在一些差异:
CONSTRUCT 查询,
但有一些限制,例如不允许 OPTIONAL。
这些限制确保变量始终被绑定;而在 SPARQL 中,某些
变量可能并未在所有模式解中绑定。
SET 形式和 SPARQL BIND 形式具有不同的错误处理
行为。在
SET 中遇到错误会导致当前解被过滤掉,而
BIND 不会在当前解中设置该变量。
SET(?var := expr) 等同于
SPARQL 中的
BIND(expr AS ?var) 后跟
FILTER(BOUND(?var))。
EXISTS 和 NOT EXISTS 不同,规则
NOT 的主体被限制为
三元组模式和过滤器。它不允许嵌套模式。
* 和 +。
COALESCE,也没有 BOUND。
没有哈希函数。
没有 RAND,因为它每次
被调用时都会产生不同结果;允许使用 NOW(),且它被定义为在
整个规则集求值过程中返回同一时间点,类似于
SPARQL 中的行为。
形状规则抽象语法是 SHACL 规则的逻辑结构。 它用于定义 SHACL 规则的执行算法。 SHACL 规则的两种具体语法形式,即形状规则语言(SRL) 和 RDF 语法(SRL/RDF),都提供了一种表达抽象语法的方式。
在三元组模式或三元组 模板中, 元组的位置 1 非正式地称为主语, 位置 2 非正式地称为谓语,而 位置 3 非正式地称为宾语。
一系列规则元素中的元素从 1 开始编号。
良构性是一组作用于 规则集抽象语法的条件。这些条件共同确保 规则头部中的 变量 在规则主体中有已定义的值; 过滤元素 或赋值表达式中的每个变量 在求值点都有值; 并且规则中的每个 赋值都会引入一个新的变量, 即该变量此前未在规则主体中使用过。
我们为给定初始变量集合的一系列规则元素 定义良构性。
令 elti 为一系列规则元素 中的第 i 个元素。
令 varsi 为由 elti 定义的变量集合,其中:
令 V0 为一个序列的初始变量。
令 Vi 为 V0 与所有 varsj 的并集, 其中 j 小于 i。
令 Vall 为 VN, 其中 N 是该序列的长度。
良构 序列是在给定变量集合 V0 的情况下, 满足以下条件的一系列规则元素:
一个规则是一个良构 规则, 如果其规则主体序列在给定 V0 为空集合的情况下是一个良构序列, 并且规则头部的 三元组模板中的每个变量 都是 Vall 的元素。
如果第二条规则的输出会影响第一条规则主体的求值,则规则
R1 依赖于规则 R2。也就是说,R2 的头部
有一个三元组模板,该模板可能生成一个三元组,与
R1 主体中的三元组模式相匹配,
无论它是作为三元组模式元素出现,还是出现在
否定元素内部。
有两种依赖:
封闭依赖和开放
依赖。
封闭依赖确保规则 R2
在规则 R1 执行之前已生成其所有可能输出。
如果规则依赖不是封闭的,则它是开放依赖,
这允许第一条规则 R1 在规则 R2 仍可能
再次运行以生成更多三元组时执行,
这些来自 R2 的新三元组随后可导致 R1 重新求值。
在第一个示例中,第一条规则对第二条规则具有开放依赖。
在第二个示例中,第一条规则对第二条规则具有封闭依赖。
如果 R1 主体中的任何
三元组模式,
无论作为三元组模式元素还是
出现在否定元素内部,
依赖
于
R2 头部中的三元组模板,
则规则 R1 依赖于 R2。
如果规则 R1 对规则
R2 的规则依赖不是
封闭依赖,
则它是开放依赖。
也就是说,R1 中依赖于
R2 的任何三元组模式都只作为
三元组模式元素出现。
规则之间的依赖关系表示为一个有向图, 称为依赖图。 图的顶点是规则集中的规则,边 根据该依赖是开放依赖还是 封闭依赖, 被标记为 open 或 closed。
R1
依赖于规则 R2,则存在一条从规则
R1 到规则 R2 的边。
该边根据该依赖是开放依赖还是
封闭依赖,
被标记为 open 或 closed。
R1 到规则 R2 的路径,
则规则 R1 对规则
R2 具有传递依赖。
依赖图不受数据图影响。
以下算法给出一种 从规则集构造 依赖 图的可能方法。一致性取决于产生一个符合依赖图定义的依赖图, 而不是取决于是否使用此过程。
define mergeLabel(oldLabel, newLabel):
## Closed dependency overrides open dependency.
if oldLabel == "open" and newLabel == "open":
return "open"
else:
return "closed"
endif
enddefine
## output -- Dependency graph with rule vertices and labeled edges.
define buildDependencyGraph(ruleSet):
## edgeLabelMap maps (R1, R2) to "open" or "closed"
let edgeLabelMap be a map from pair (rule, rule) to label
foreach rule R1 in ruleSet:
## Classify each triple pattern TP in the rule as requiring "open" or "closed"
## depending on whether it is in a negation element or not.
let bodyDependencies = {}
foreach rule element RBE in the body of R1:
if RBE is a negation element:
foreach triple pattern TP in RBE:
let item be a pair (TP, "closed")
add item to bodyDependencies
endfor
else if RBE is a triple pattern element of triple pattern TP:
let item be a pair (TP, "open")
add item to bodyDependencies
else if RBE is a condition element:
## Do nothing
else if RBE is an assignment element:
## Do nothing
endif
endfor
foreach pair (triple pattern TP, depLabel) in bodyDependencies:
if R1 has an assignment element:
set depLabel to "closed"
endif
if R1 has a triple template with a blank node:
set depLabel to "closed"
endif
## Find depenencies for this triple pattern element or negation element.
foreach rule R2 in ruleSet:
foreach triple template TT in head of R2:
## "possibly generate" / matching is defined in
## section 3.3
if TT can possibly match triple pattern TP:
let key = (R1, R2)
if edgeLabelMap contains key:
let oldLabel = edgeLabelMap.get(key)
let merged = mergeLabel(oldLabel, depLabel)
edgeLabelMap.set(key, merged)
else:
edgeLabelMap.set(key, depLabel)
endif
endif
endfor
endfor
endfor
endfor
let DP = { }
foreach entry ((R1, R2), label) in edgeLabelMap:
add edge (R1 -> R2) labeled label to DP
endfor
the result is DP
enddefine
示例:
分层是将规则集 划分为一个有序的分层层级序列的过程(也称为 “strata”,单数为 “stratum”)。较低分层中的规则 会先于较高分层中的规则求值。
分层对规则之间的依赖施加约束, 以确保否定元素、赋值 元素,以及在规则头部中创建的空白节点, 仅依赖于使用更早(更低)分层和 基础图计算出的结果。 这保证了对给定基础图上的规则集求值会得到单一、明确定义且有限的 结果。
分层过程也可以用于作出其他求值 决策。本文档描述了一致求值所需的条件, 并给出一种可能的分层形成方式。 实现需要满足此处描述的条件 才能获得兼容行为,但并不要求 按照所呈现的算法实现。
分层层级 SL 是一对
互不相交的规则集合
(SL.once、SL.general)。
SL.once 包含只运行一次规则,即
使用赋值元素或
在规则头部中产生空白节点的规则;
这些规则会在该分层层级求值开始时各自恰好
求值一次。
SL.general 包含其余规则,这些规则会被反复求值,
直到不再推断出新的三元组。
只有在满足以下条件时,才定义 分层。 如果某个规则集不满足此条件,那么本 规范不会为此类规则集的求值结果作出定义。
以下算法给出一种仅基于规则集的可能分层方式。
## output -- Map: Integer -> Set of rules.
define stratification(ruleSet):
let DP = Dependency graph for the rule set.
let stratumMap be a map from rule to integer
## The dependency graph should satisfy the stratification condition.
## The check for unbounded stratification is a guard
## due to a violation of the stratification condition.
let limit = num rules + 1
let maxStratum = 0
## initialize stratumMap
foreach rule in ruleSet:
stratumMap.set(rule, 0)
endfor
boolean changed = true;
while changed:
changed = false;
foreach edge E in DP:
## Edge from pRule to qRule with a label
let pRule = source of edge
let qRule = destination of the edge
let label = edge label
if label == "open" :
if stratumMap.get(pRule) < stratumMap.get(qRule) :
stratumMap.set(pRule, stratumMap.get(qRule))
changed = true;
endif
endif
if label == "closed" :
if stratumMap.get(pRule) <= stratumMap.get(qRule) :
let xStratum = 1 + stratumMap.get(qRule)
if ( xStratum > limit )
## Stratification requirement violated
error "Stratification error"
endif
stratumMap.set(pRule, xStratum)
maxStratum = max(maxStratum, xStratum)
changed = true;
endif
endif
endfor
endwhile
## Initialize the result map.
let stratumRules be a map from integer to rules.
for i = 0 to maxStratum
stratumRules.set(i, {})
endfor
## Gather rules in stratumMap with the same level number
for rule R in map stratumMap:
let stratumNum = stratumMap.get(R)
add R to stratumRules.get(stratumNum)
endfor
## Partition each level into once and general
let stratumLevels be a sequence of pairs of sets of rules.
for i = 0 to maxStratum:
let rules = stratumRules.get(i)
let once = { R in rules | R is a run-once rule }
let general = rules \ once
stratumLevels.set(i, pair(once, general))
endfor
the result is stratumLevels
enddefine
存在两种具体语法。
形状规则语言:
RDF 规则语法:
语法如下所示。
将 AST 映射到抽象语法。
附加辅助项(简写缩写):
这些允许使用常见规则模式,也允许基础引擎中 的专用实现。
TRANSITIVE(uri)SYMMETRIC(uri)INVERSE(uri, uri)
词汇表:rdf-syntax-vocab.ttl
SHACL 形状:rdf-syntax-shapes.ttl
良构性:
描述抽象模型如何映射到三元组。
过程:累加器,自底向上/遍历结构。
不在语法中的所有三元组都会被忽略。 不允许其他 "srl:" 谓词(??)。
@@ 插图:文本和 RDF 语法中的 SHACL 规则集:全部特性:
PREFIX : <http://example/>
DATA { :s :p :o }
RULE { ?x :q :o } WHERE { ?x :p :o }
RULE { ?x :q :o } WHERE { ?x :p :o1 ; :p :o2 }
RULE { ?x :q :o } WHERE { ?x :p ?o . FILTER (?o < 18) }
RULE { ?x :q ?o } WHERE { ?x :p :o . SET (?o := 18) }
RULE { ?x :q ?o } WHERE { ?x :p :o . NOT { ?s :p ?o . FILTER(?o < 18) } }
PREFIX : <http://example/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX sh: <http://www.w3.org/ns/shacl#>
PREFIX sparql: <http://www.w3.org/ns/sparql#>
PREFIX srl: <http://www.w3.org/ns/shacl-rules#>
:ruleSet-1
rdf:type srl:RuleSet;
srl:data (
[ srl:subject :s ; srl:predicate :p; srl:object :o ; ]
);
srl:rules (
[
rdf:type srl:Rule;
srl:body (
[ srl:subject [ srl:varName "x" ] ; srl:predicate :p ; srl:object :o ; ]
) ;
srl:head (
[ srl:subject [ srl:varName "x" ] ; srl:predicate :q ; srl:object :o ; ]
)
]
[
rdf:type srl:Rule ;
srl:body (
[ srl:subject [ srl:varName "x" ] ; srl:predicate :p ; srl:object :o1 ; ]
[ srl:subject [ srl:varName "x" ] ; srl:predicate :p ; srl:object :o2 ; ]
) ;
srl:head (
[ srl:subject [ srl:varName "x" ] ; srl:predicate :q ; srl:object :o ; ]
)
]
[
rdf:type srl:Rule ;
srl:body (
[ srl:subject [ srl:varName "x" ] ; srl:predicate :p ; srl:object [ srl:varName "o" ] ; ]
[
srl:filter [
sparql:less-than (
[ srl:varName "o" ]
18
)
]
]
) ;
srl:head (
[ srl:subject [ srl:varName "x" ] ; srl:predicate :q ; srl:object :o ; ]
)
]
[
rdf:type srl:Rule ;
srl:body (
[ srl:subject [ srl:varName "x" ] ; srl:predicate :p ; srl:object :o ; ]
[
srl:assign [
srl:assignValue 18 ;
srl:assignVar [ srl:varName "o" ]
]
]
) ;
srl:head (
[ srl:subject [ srl:varName "x" ] ; srl:predicate :q ; srl:object [ srl:varName "o" ] ; ]
)
]
[
rdf:type srl:Rule ;
srl:body (
[ srl:subject [ srl:varName "x" ] ; srl:predicate :p ; srl:object :o ; ]
[
srl:not (
[ srl:subject [ srl:varName "s" ] ; srl:predicate :p ; srl:object [ srl:varName "o" ] ; ]
[
srl:filter [
sparql:less-than (
[ srl:varName "o" ]
18
)
]
]
)
]
) ;
srl:head (
[ srl:subject [ srl:varName "x" ] ; srl:predicate :q ; srl:object [ srl:varName "o" ] ; ]
)
]
) .
本节定义在给定数据上对规则集求值的结果。 它并不规定该算法作为实现方法。 实现可以使用任何能生成相同结果的算法。
输入: 数据图 G,称为基础图,以及规则集 RS。
输出: 由推理三元组组成的 RDF 图 GI
推理出的三元组不包括 基础图的三元组集合中已有的三元组。
μ : V → T,
其中 V 是所有变量的集合,
T 是所有 RDF
术语的集合。
μ 的定义域记作
dom(μ),它是
V 中 μ 有定义的子集。在明确表示
解映射时,我们使用术语
解。
将 μ0 写作这样的解映射:
dom(μ0) 是空集合。
subst(μ, 三元组模式),
它返回一个三元组模式,
其中三元组模式中每个属于
dom(μ)
的变量出现处,都被该 var 的
解映射给出的
RDF 术语替换。
如果所得三元组模式没有变量,那么它就是一个 RDF 三元组。
令 G 为一个 RDF 图,TP 为一个
三元组模式。
函数 graphMatch(G, TP) 返回所有可能
解的集合;
这些解应用于该三元组模式时,会产生一个存在于
求值图中的三元组
令 S1 和 S2 为解。
compatible(μ1, μ2) = true
if forall v in dom(μ1) intersection dom(μ2)
μ1(v) = μ2(v)
compatible(μ1, μ2) = false otherwise
merge(μ1, μ2) = { μ |
μ(v) = μ1(v) if v in dom(μ1)
μ(v) = μ2(v) otherwise }
merge(S1, S2) = { μ |
μ1 in S1, μ2 in S2
and compatible(μ1, μ2)
μ(v) = merge(μ1, μ2) }
说明定义域是 dom(S1) ∪︀ dom(S2)。
说明两个没有共有变量的解是兼容的。
对规则集求值的第一步,是准备一个单一的、 有效的规则集。这包括收集所有被导入的规则集, 构建一个单一的组合规则集,然后为该组合规则集计算 分层。
已解析规则集通过递归读取另一个 规则集的导入项中提到的所有规则集, 从该规则集生成。
一个规则集有三个组件:R.rules、
R.data 和 R.imports。
两个规则集 RS1 和 RS2 的
规则
集合并
是一个规则集 MR,定义如下:
MR.rules = RS1.rules ∪︀ RS2.rules
MR.data = merge(RS1.data, RS2.data)
MR.imports = {}
其中 merge 是
RDF 合并
操作。
define imports(rule set RS, set of URLs V), returning rule set
let I = the set of import URLs declared for the rule set RS
let RS2 be a rule set formed from RS.rules and RS.data
foreach URL x in I:
if x ∉ V:
V = V ∪︀ { x }
read rule set RS3 from URL x
RS2 = rulesetMerge(RS2, imports(RS3, V))
endif
endfor
result is RS2
enddefine
let RS be a rule set
let V = {}
if RS has a location, V = { location of RS }
result is imports(RS, V)
创建已解析规则集后,计算 依赖图 (参见 4.3.2 依赖图算法), 然后计算一个 [=stratification] (参见 4.4.2 分层算法)。
表达式无论是用于过滤元素还是 赋值元素,都会相对于一个 解映射求值;该解映射为表达式中的每个变量提供一个 RDF 术语值。 4.2 良构性条件 中的良构性要求确保表达式中的所有变量 都出现在解映射中。
define evalFunction(F, μ):
## F is an expression: an RDF term, a variable, or op(expr1, ..., exprN)
## where op is a function or a functional form.
if F is an RDF term:
return F
if F is a variable:
## By well-formedness, F ∈ dom(μ).
return μ(F)
## F is of the form F= op(expr1, ..., exprN)
if op is a functional form (e.g. IF, logical-or):
## Evaluated specifically for op; op may evaluate only some arguments.
## For example, IF(c, t, f) evaluates c, then exactly one of t or f.
return the value defined for op over expr1, ..., exprN under μ
## op is an ordinary function: evaluate all arguments first.
return F(evalFunction(expr1, row), ..., evalFunction(exprN, row))
enddefine
函数 EBV(x) 返回一个 RDF 术语的
有效布尔值。
对规则求值,是通过从规则主体计算一个解 序列, 然后使用该解序列中的每个 解映射, 用规则头部生成三元组。
let R be a well-formed rule.
let rule R = (H, B) where
H is the sequence of triple templates in the head
B is the sequence of triple pattern elements,
condition elements, negation elements,
and assignment elements in the body
# Solution sequence of one solution that does not map any variables.
let SEQ0: Solution sequence = { μ0 }
let G = evaluation graph
# Evaluate rule body
# This function returns a sequence of solutions
define evalRuleElements(B, SEQ, G):
for each rule element rElt in B:
if rElt is a triple pattern TP:
X = graphMatch(G, TP)
SEQ1 = {}
for each μ1 in X:
for each μ2 in SEQ:
if compatible(μ1, μ2)
μ3 = merge(μ1, μ2)
add μ3 to SEQ1
endif
endfor
endfor
endif
if rElt is a condition element with expression F:
SEQ1 = {}
for each solution μ in SEQ:
let x = evalFunction(F, μ)
if EBV(x) is true:
add μ to SEQ1
endif
endfor
endif
if rElt is a negation expression with body elements N:
SEQ1 = {}
for each solution μ in SEQ:
S = sequence{ μ }
NEG = evalRuleElements(N, S, G)
if NEG is empty
add μ to SEQ1
endif
endfor
endif
if rElt is an assignment with variable V and expression expr
SEQ1 = {}
for each solution μ in SEQ:
let x = evalFunction(expr, μ)
if x is not an error:
## Add mapping V -> x to solution μ
let μ2 be a solution mapping μ ∪︀ { (V, x) }
add μ2 to SEQ1
else
# Error: drop solution μ
endif
endfor
endif
if SEQ1 is empty
SEQ = {}
return SEQ
endif
SEQ = SEQ1
endfor
return SEQ
enddefine
let SEQ = evalRuleElements(B, SEQ0, G)
# Evaluate rule head
let OUT = empty set
for each μ in SEQ:
let S = {}
for each triple template TT in H:
let triple = subst(μ, TT)
Add triple to S
endfor
OUT = OUT union S
endfor
result eval(R, G) is OUT
注意,OUT 可能包含数据图中已有的三元组。
规则集的求值被定义为执行该规则集 分层中的每个 分层; 其中每个分层都会先按顺序完整执行, 然后再进入下一个分层。 对一个分层求值时,首先对该分层中的每个 只运行一次规则求值,然后反复求值该分层中的 一般规则,直到不再产生新的三元组。
let G0 be the input base graph
let RS be the rule set
let D be the graph of all DATA triples in RS
Apply stratification to RS
let LS be the sequence of layers after stratification
# Inference graph
let GI = { t ∈ D | t ∉ G0 }
# Evaluation graph.
let GE = G0 ∪︀ D
for each stratum ST in LS:
for each rule R in ST.once:
let X = eval(R, GE)
let Y = { t ∈ X | t ∉ GE }
GI = Y ∪︀ GI
GE = Y ∪︀ GE
endfor
let finished = false
while !finished:
finished = true
for each rule R in ST.general:
let X = eval(R, GE)
let Y = { t ∈ X | t ∉ GE }
if Y is not empty:
finished = false
GI = Y ∪︀ GI
GE = Y ∪︀ GE
endif
endfor
endwhile
endfor
the result is GI
形状规则语言文档是一个以 UTF-8
编码的 RDF
字符串
[RFC3629]。
仅允许使用
Unicode 标量值,
范围为 U+0000 到 U+D7FF
以及 U+E000 到 U+10FFFF。
这排除了
代理码点,
即 U+D800 到 U+DFFF 范围。
空白
(产生式 WS)用于
分隔两个否则会被(错误地)识别为一个终结符的终结符。
下方以大写表示的规则名指示空白具有重要意义的位置;
这些规则构成了用于构造形状规则语言解析器的一种可能终结符选择。
空白在产生式
String 中具有重要意义。
注释以位于
IRIREF、
STRING_LITERAL1、
STRING_LITERAL2、
STRING_LITERAL_LONG1 或
STRING_LITERAL_LONG2
之外的 # 开始,
并持续到行尾(由
LF 或
CR 标记),
如果注释标记之后没有行尾,则持续到文件结尾。
注释被视为空白。
相对 IRI 引用按照 统一资源标识符(URI):通用 语法 [RFC3986], 使用第 5.2 节中的基本算法,通过基准 IRI 进行解析。 不执行基于语法的规范化或基于方案的规范化 (RFC3986 第 6.2.2 和 6.2.3 节中所述)。 IRI 引用中额外允许的字符,按 国际化资源标识符 (IRI) [RFC3987] 第 6.5 节所述,以与 URI 引用中未保留字符相同的方式处理。
BASE
指令定义用于解析
相对 IRI
引用的基准 IRI,依据 [RFC3986]
第 5.1.1 节,“内容中嵌入的基准 URI”。
第 5.1.2 节,“来自封装实体的基准
URI”
定义作用域内基准 IRI 如何来自封装文档,
例如带有 xml:base 指令的 SOAP 信封,或带有
Content-Location 标头的 MIME multipart 文档。
5.1.3,来自检索
URI 的基准 URI中标识的“检索 URI”,
是特定形状规则语言文档
被检索自的 URL。
如果以上均未指定基准 URI,则使用默认
基准 URI(第 5.1.4 节,“默认基准 URI”)。
每个 BASE 指令都会相对于前一个基准 URI
设置新的作用域内基准 URI。
形状规则文档中使用三种形式的转义:
数字转义序列表示 一个 Unicode 码点的值。
数字转义序列
MUST NOT 产生
U+D800 到 U+DFFF 范围内的码点值,
该范围是 Unicode
代理项范围。
| 转义序列 | Unicode 码点 |
|---|---|
\u hex
hex
hex
hex
|
位于 U+0000 到 U+D7FF
以及 U+E000 到 U+FFFF
范围内的 Unicode 码点,
对应于按从最高有效位到最低有效位解释的四个十六进制数字所编码的值。 |
\U hex
hex
hex
hex
hex
hex
hex
hex
|
位于 U+0000 到
U+D7FF
以及 U+E000 到 U+10FFFF
范围内的 Unicode 码点,
对应于按从最高有效位到最低有效位解释的八个十六进制数字所编码的值。
|
其中 hex 是一个十六进制字符
HEX ::= [0-9] | [A-F] |
[a-f]
字符串转义序列表示传统上在字符串字面量中 被转义的字符:
| 转义序列 | Unicode 码点 |
|---|---|
\t |
U+0009 |
\b |
U+0008 |
\n |
U+000A |
\r |
U+000D |
\f |
U+000C |
\" |
U+0022 |
\' |
U+0027 |
\\ |
U+005C |
保留字符转义序列由一个
\ 后跟
这些字符之一 ~.-!$&'()*+,;=/?#@%_ 组成,
并表示
\ 右侧的字符。
| 数字 转义 |
字符串 转义 |
保留字符 转义 |
|
|---|---|---|---|
IRI,
用作 RDF 术语、
PREFIX,
或 BASE 声明
|
是 | 否 | 否 |
| 局部名称 | 否 | 否 | 是 |
| 字符串 | 是 | 是 | 否 |
此处使用的 EBNF 在 XML 1.0 [EBNF-NOTATION] 中定义。
说明:
[1] |
RuleSet |
::= | RuleOrDataBlock |
[2] |
RuleOrDataBlock |
::= | Prologue ( RuleOrData+ ( Prologue1 RuleOrData? )* )?
|
[3] |
RuleOrData |
::= | Rule | Data
|
[4] |
Prologue |
::= | Prologue1* |
[5] |
Prologue1 |
::= | BaseDecl | PrefixDecl | VersionDecl | ImportsDecl
|
[6] |
BaseDecl |
::= | 'BASE' IRIREF
|
[7] |
PrefixDecl |
::= | 'PREFIX' PNAME_NS IRIREF
|
[8] |
VersionDecl |
::= | 'VERSION' VersionSpecifier
|
[9] |
VersionSpecifier
|
::= | STRING_LITERAL1 | STRING_LITERAL2
|
[10] |
ImportsDecl |
::= | 'IMPORTS' iri
|
[11] |
Rule |
::= | Rule1 | Rule2 | Declaration
|
[12] |
Rule1 |
::= | 'RULE' iri? HeadTemplate 'WHERE' BodyPattern
|
[13] |
Rule2 |
::= | 'IF' BodyPattern 'THEN' HeadTemplate
|
[14] |
Declaration |
::= | ( 'TRANSITIVE' '(' iri ')' | 'SYMMETRIC' '(' iri ')' | 'INVERSE' '(' iri ',' iri ')' )
|
[15] |
Data |
::= | 'DATA' '{' TriplesDataBlock? '}'
|
[16] |
TriplesDataBlock
|
::= | TriplesSameSubject ( '.' TriplesDataBlock? )?
|
[17] |
HeadTemplate |
::= | '{' HeadTemplateBlock? '}'
|
[18] |
BodyPattern |
::= | '{' BodyTriplesBlock? ( BodyNotTriples '.'? BodyTriplesBlock? )* '}'
|
[19] |
BodyNotTriples |
::= | Filter | Negation | Assignment
|
[20] |
BodyTriplesBlock
|
::= | TriplesBlock |
[21] |
Negation |
::= | 'NOT' '{' BodyBasic '}'
|
[22] |
BodyBasic |
::= | BodyTriplesBlock? ( BodyBasicNotTriples '.'? BodyTriplesBlock? )*
|
[23] |
BodyBasicNotTriples
|
::= | Filter |
[24] |
HeadTemplateBlock
|
::= | TriplesBlock |
[25] |
TriplesBlock |
::= | TriplesSameSubjectPath ( '.' TriplesBlock? )?
|
[26] |
ReifiedTripleBlock
|
::= | ReifiedTriple PropertyList
|
[27] |
ReifiedTripleBlockPath
|
::= | ReifiedTriple PropertyListPath
|
[28] |
Assignment |
::= | 'SET' '(' Var ':=' Expression ')'
|
[29] |
Reifier |
::= | '~' VarOrReifierId?
|
[30] |
VarOrReifierId |
::= | Var | iri | BlankNode
|
[31] |
Filter |
::= | 'FILTER' Constraint
|
[32] |
Constraint |
::= | BrackettedExpression | BuiltInCall | FunctionCall
|
[33] |
FunctionCall |
::= | iri ArgList
|
[34] |
ArgList |
::= | NIL | '(' Expression ( ',' Expression )* ')'
|
[35] |
ExpressionList |
::= | NIL | '(' Expression ( ',' Expression )* ')'
|
[36] |
TriplesSameSubject
|
::= | VarOrTerm PropertyListNotEmpty | TriplesNode PropertyList | ReifiedTripleBlock
|
[37] |
PropertyList |
::= | PropertyListNotEmpty?
|
[38] |
PropertyListNotEmpty
|
::= | Verb ObjectList ( ';' ( Verb ObjectList )? )*
|
[39] |
Verb |
::= | VarOrIri | 'a'
|
[40] |
ObjectList |
::= | Object ( ',' Object )*
|
[41] |
Object |
::= | GraphNode Annotation
|
[42] |
TriplesSameSubjectPath
|
::= | VarOrTerm PropertyListPathNotEmpty | TriplesNodePath PropertyListPath | ReifiedTripleBlockPath
|
[43] |
PropertyListPath
|
::= | PropertyListPathNotEmpty?
|
[44] |
PropertyListPathNotEmpty
|
::= | ( VerbPath | VerbSimple ) ObjectListPath ( ';' ( ( VerbPath | VerbSimple ) ObjectListPath )? )*
|
[45] |
VerbPath |
::= | Path |
[46] |
VerbSimple |
::= | Var |
[47] |
ObjectListPath |
::= | ObjectPath ( ',' ObjectPath )*
|
[48] |
ObjectPath |
::= | GraphNodePath AnnotationPath
|
[49] |
Path |
::= | PathSequence |
[50] |
PathSequence |
::= | PathEltOrInverse ( '/' PathEltOrInverse )*
|
[51] |
PathEltOrInverse
|
::= | PathElt | '^' PathElt
|
[52] |
PathElt |
::= | PathPrimary |
[53] |
PathPrimary |
::= | iri | 'a' | '(' Path ')'
|
[54] |
TriplesNode |
::= | Collection | BlankNodePropertyList
|
[55] |
BlankNodePropertyList
|
::= | '[' PropertyListNotEmpty ']'
|
[56] |
TriplesNodePath |
::= | CollectionPath | BlankNodePropertyListPath
|
[57] |
BlankNodePropertyListPath
|
::= | '[' PropertyListPathNotEmpty ']'
|
[58] |
Collection |
::= | '(' GraphNode+ ')'
|
[59] |
CollectionPath |
::= | '(' GraphNodePath+ ')'
|
[60] |
AnnotationPath |
::= | ( Reifier | AnnotationBlockPath )*
|
[61] |
AnnotationBlockPath
|
::= | '{|' PropertyListPathNotEmpty '|}'
|
[62] |
Annotation |
::= | ( Reifier | AnnotationBlock )*
|
[63] |
AnnotationBlock |
::= | '{|' PropertyListNotEmpty '|}'
|
[64] |
GraphNode |
::= | VarOrTerm | TriplesNode | ReifiedTriple
|
[65] |
GraphNodePath |
::= | VarOrTerm | TriplesNodePath | ReifiedTriple
|
[66] |
VarOrTerm |
::= | Var | RDFTerm
|
[67] |
RDFTerm |
::= | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | NIL | TripleTerm
|
[68] |
ReifiedTriple |
::= | '<<' ReifiedTripleSubject Verb ReifiedTripleObject Reifier? '>>'
|
[69] |
ReifiedTripleSubject
|
::= | Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTriple | TripleTerm
|
[70] |
ReifiedTripleObject
|
::= | Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTriple | TripleTerm
|
[71] |
TripleTerm |
::= | '<<(' TripleTermSubject Verb TripleTermObject ')>>'
|
[72] |
TripleTermSubject
|
::= | Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTerm
|
[73] |
TripleTermObject
|
::= | Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTerm
|
[74] |
TripleTermData |
::= | '<<(' TripleTermDataSubject ( iri | 'a' ) TripleTermDataObject ')>>'
|
[75] |
TripleTermDataSubject
|
::= | iri | RDFLiteral | NumericLiteral | BooleanLiteral
|
[76] |
TripleTermDataObject
|
::= | iri | RDFLiteral | NumericLiteral | BooleanLiteral | TripleTermData
|
[77] |
VarOrIri |
::= | Var | iri
|
[78] |
Var |
::= | VAR1 | VAR2
|
[79] |
Expression |
::= | ConditionalOrExpression
|
[80] |
ConditionalOrExpression
|
::= | ConditionalAndExpression ( '||' ConditionalAndExpression )*
|
[81] |
ConditionalAndExpression
|
::= | ValueLogical ( '&&' ValueLogical )*
|
[82] |
ValueLogical |
::= | RelationalExpression
|
[83] |
RelationalExpression
|
::= | NumericExpression ( '=' NumericExpression | '!=' NumericExpression | '<' NumericExpression | '>' NumericExpression | '<=' NumericExpression | '>=' NumericExpression | 'IN' ExpressionList | 'NOT' 'IN' ExpressionList )?
|
[84] |
NumericExpression
|
::= | AdditiveExpression
|
[85] |
AdditiveExpression
|
::= | MultiplicativeExpression ( '+' MultiplicativeExpression | '-' MultiplicativeExpression | ( NumericLiteralPositive | NumericLiteralNegative ) ( ( '*' UnaryExpression ) | ( '/' UnaryExpression ) )* )*
|
[86] |
MultiplicativeExpression
|
::= | UnaryExpression ( '*' UnaryExpression | '/' UnaryExpression )*
|
[87] |
UnaryExpression |
::= | '!' PrimaryExpression
|
[88] |
PrimaryExpression
|
::= | BrackettedExpression | BuiltInCall | iriOrFunction | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprTripleTerm
|
[89] |
ExprTripleTerm |
::= | '<<(' ExprTripleTermSubject Verb ExprTripleTermObject ')>>'
|
[90] |
ExprTripleTermSubject
|
::= | iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var
|
[91] |
ExprTripleTermObject
|
::= | iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprTripleTerm
|
[92] |
BrackettedExpression
|
::= | '(' Expression ')'
|
[93] |
BuiltInCall |
::= | 'STR' '(' Expression ')'
|
[94] |
iriOrFunction |
::= | iri ArgList?
|
[95] |
RDFLiteral |
::= | String ( LANG_DIR | '^^' iri )?
|
[96] |
NumericLiteral |
::= | NumericLiteralUnsigned | NumericLiteralPositive | NumericLiteralNegative
|
[97] |
NumericLiteralUnsigned
|
::= | INTEGER | DECIMAL | DOUBLE
|
[98] |
NumericLiteralPositive
|
::= | INTEGER_POSITIVE | DECIMAL_POSITIVE | DOUBLE_POSITIVE
|
[99] |
NumericLiteralNegative
|
::= | INTEGER_NEGATIVE | DECIMAL_NEGATIVE | DOUBLE_NEGATIVE
|
[100] |
BooleanLiteral |
::= | 'true' | 'false'
|
[101] |
String |
::= | STRING_LITERAL1 | STRING_LITERAL2 | STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2
|
[102] |
iri |
::= | IRIREF | PrefixedName
|
[103] |
PrefixedName |
::= | PNAME_LN | PNAME_NS
|
[104] |
BlankNode |
::= | BLANK_NODE_LABEL | ANON
|
终结符产生式:
[105] |
IRIREF |
::= | '<' ([^<>"{}|^`\]-[#x00-#x20] | UCHAR )* '>'
|
[106] |
PNAME_NS |
::= | PN_PREFIX? ':' |
[107] |
PNAME_LN |
::= | PNAME_NS PN_LOCAL
|
[108] |
BLANK_NODE_LABEL
|
::= | '_:' ( PN_CHARS_U | [0-9] ) ((PN_CHARS|'.')* PN_CHARS)?
|
[109] |
VAR1 |
::= | '?' VARNAME |
[110] |
VAR2 |
::= | '$' VARNAME |
[111] |
LANG_DIR |
::= | '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)* ('--' [a-zA-Z]+)?
|
[112] |
INTEGER |
::= | [0-9]+ |
[113] |
DECIMAL |
::= | [0-9]* '.' [0-9]+ |
[114] |
DOUBLE |
::= | ( ([0-9]+ ('.'[0-9]*)? ) | ( '.' ([0-9])+ ) ) [eE][+-]?[0-9]+
|
[115] |
INTEGER_POSITIVE
|
::= | '+' INTEGER
|
[116] |
DECIMAL_POSITIVE
|
::= | '+' DECIMAL
|
[117] |
DOUBLE_POSITIVE |
::= | '+' DOUBLE
|
[118] |
INTEGER_NEGATIVE
|
::= | '-' INTEGER
|
[119] |
DECIMAL_NEGATIVE
|
::= | '-' DECIMAL
|
[120] |
DOUBLE_NEGATIVE |
::= | '-' DOUBLE
|
[121] |
STRING_LITERAL1 |
::= | "'" ( ([^#x27#x5C#xA#xD]) | ECHAR | UCHAR )* "'"
|
[122] |
STRING_LITERAL2 |
::= | '"' ( ([^#x22#x5C#xA#xD]) | ECHAR | UCHAR )* '"'
|
[123] |
STRING_LITERAL_LONG1
|
::= | "'''" ( ( "'" | "''" )? ( [^'\] | ECHAR | UCHAR ) )* "'''"
|
[124] |
STRING_LITERAL_LONG2
|
::= | '"""' ( ( '"' | '""' )? ( [^"\] | ECHAR | UCHAR ) )* '"""'
|
[125] |
ECHAR |
::= | '\' [tbnrf\"'] |
[126] |
UCHAR |
::= | ('\u' HEX HEX HEX HEX) | ('\U' HEX HEX HEX HEX HEX HEX HEX HEX)
|
[127] |
NIL |
::= | '(' WS* ')' |
[128] |
WS |
::= | #x20 | #x9 | #xD | #xA |
[129] |
ANON |
::= | '[' WS* ']' |
[130] |
PN_CHARS_BASE |
::= | [A-Z] | [a-z] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x02FF] | [#x0370-#x037D] | [#x037F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
|
[131] |
PN_CHARS_U |
::= | PN_CHARS_BASE | '_'
|
[132] |
VARNAME |
::= | ( PN_CHARS_U | [0-9] ) ( PN_CHARS_U | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040] )*
|
[133] |
PN_CHARS |
::= | PN_CHARS_U | '-' | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040]
|
[134] |
PN_PREFIX |
::= | PN_CHARS_BASE ((PN_CHARS|'.')* PN_CHARS)?
|
[135] |
PN_LOCAL |
::= | (PN_CHARS_U | ':' | [0-9] | PLX ) ((PN_CHARS | '.' | ':' | PLX)* (PN_CHARS | ':' | PLX) )?
|
[136] |
PLX |
::= | PERCENT | PN_LOCAL_ESC
|
[137] |
PERCENT |
::= | '%' HEX HEX
|
[138] |
HEX |
::= | [0-9] | [A-F] | [a-f] |
[139] |
PN_LOCAL_ESC |
::= | '\' ( '_' | '~' | '.' | '-' | '!' | '$' | '&' | "'" | '(' | ')' | '*' | '+' | ',' | ';' | '=' | '/' | '?' | '#' | '@' | '%' )
|
该语法的文本版本可在 此处获取。
本文档使用一些特定的终结符字面字符串 [EBNF-NOTATION]。为阐明这些 终结符字面字符串所使用的 Unicode 码点, 下表描述了本节中使用的特定字符。
| 编码 | 字形 | 描述 |
|---|---|---|
U+000A |
LF |
换行 |
U+000D |
CR |
回车 |
U+0023 |
# |
数字符号 |
U+0025 |
% |
百分号 |
U+005C |
\ |
反斜杠 |
形状规则语言的互联网媒体类型(以前称为 MIME 类型)是
"application/shape-rules"。
以下信息已提交给互联网工程指导组(IESG),以供审查、批准并向 IANA 注册。
versionversion 的可接受值在
版本标签中定义。
profileprofile 参数的值是一个由空格分隔的非空 URI 列表。
有关更多信息和背景,请参阅 [RFC6906]。
本节为非规范性内容。
TODO
本节为非规范性内容。
TODO
本节为非规范性内容。
TODO
本节为非规范性内容。
TODO
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: