Skip to main content

2. Syntax (语法)

URI模板是一个可打印Unicode字符的字符串,包含零个或多个嵌入的变量表达式 (Variable Expressions),每个表达式由一对匹配的花括号 (', ') 定界。

URI-Template  = *( literals / expression )

尽管上面按照四个渐进级别描述了模板(和模板处理器实现),但我们根据Level 4的ABNF定义URI模板语法。限于较低级别模板的模板处理器可以 (MAY) 排除仅适用于较高级别的ABNF规则。但是,建议 (RECOMMENDED) 所有解析器实现完整语法,以便可以向最终用户正确识别不支持的级别。

2.1. Literals (字面量)

URI模板字符串中表达式之外的字符意图按字面复制到URI引用,如果该字符在URI中允许 (reserved / unreserved / pct-encoded),或者如果不允许,则作为对应于该字符在UTF-8 [RFC3629] 中编码的百分号编码三元组序列复制到URI引用。

literals      =  %x21 / %x23-24 / %x26 / %x28-3B / %x3D / %x3F-5B
/ %x5D / %x5F / %x61-7A / %x7E / ucschar / iprivate
/ pct-encoded
; 任何Unicode字符,除了: CTL, SP,
; DQUOTE, "'", "%" (除了pct-encoded),
; "<", ">", "\", "^", "`", "{", "|", "}"

2.2. Expressions (表达式)

模板表达式是URI模板的参数化部分。每个表达式包含一个可选的运算符 (Operator),它定义表达式类型及其对应的扩展过程,后跟一个逗号分隔的变量规格符 (Variable Specifiers) 列表(变量名和可选的值修饰符)。如果没有提供运算符,表达式默认为未保留值的简单变量扩展。

expression    =  "{" [ operator ] variable-list "}"
operator = op-level2 / op-level3 / op-reserve
op-level2 = "+" / "#"
op-level3 = "." / "/" / ";" / "?" / "&"
op-reserve = "=" / "," / "!" / "@" / "|"

运算符字符的选择反映了它们在URI通用语法中作为保留字符的角色。本规范第3节中定义的运算符包括:

  • + 保留字符串 (Reserved character strings)
  • # 由 "#" 前缀的片段标识符 (Fragment identifiers)
  • . 由 "." 前缀的名称标签或扩展 (Name labels or extensions)
  • / 由 "/" 前缀的路径段 (Path segments)
  • ; 由 ";" 前缀的路径参数名或 name=value 对 (Path parameter name or name=value pairs)
  • ? 以 "?" 开始并由 "&" 分隔的 name=value 对组成的查询组件 (Query component)
  • & 字面查询组件内查询风格 &name=value 对的续接 (Continuation of query-style pairs)

运算符字符等号 ("=")、逗号 (",")、感叹号 ("!")、at符号 ("@") 和竖线 ("|") 保留用于未来扩展。

表达式语法特别排除了美元符号 ("$") 和括号 ["(" 和 ")"] 字符的使用,以使它们可用于本规范范围之外。例如,宏语言可能使用这些字符在将字符串作为URI模板处理之前对字符串应用宏替换。

2.3. Variables (变量)

在运算符(如果有)之后,每个表达式包含一个或多个逗号分隔的变量规格符 (varspec) 列表。变量名具有多种用途:记录期望的值类型、模板处理器内关联值的标识符,以及在 name=value 扩展中用作名称的字面字符串(除了展开关联数组时)。变量名区分大小写,因为名称可能在区分大小写的URI组件中扩展。

variable-list =  varspec *( "," varspec )
varspec = varname [ modifier-level4 ]
varname = varchar *( ["."] varchar )
varchar = ALPHA / DIGIT / "_" / pct-encoded

varname 可以 (MAY) 包含一个或多个百分号编码的三元组。这些三元组被视为变量名的基本部分,在处理期间不会被解码。包含百分号编码字符的 varname 与具有这些相同字符已解码的 varname 不是同一个变量。提供URI模板的应用程序应该在变量名中一致使用百分号编码。

表达式可以 (MAY) 引用模板处理器未知的变量或其值设置为特殊 "undefined (未定义)" 值(如 undef 或 null)的变量。这些未定义的变量在扩展过程中会得到特殊处理(第3.2.1节)。

长度为零的字符串的变量值不被视为未定义;它具有空字符串的已定义值。

在Level 4模板中,变量可以具有值列表或 (name, value) 对的关联数组形式的复合值 (Composite Value)。这些值类型不是由模板语法直接指示的,但它们确实对扩展过程有影响(第3.2.1节)。

如果列表包含零个成员,则定义为列表值的变量被视为未定义。如果数组包含零个成员或数组中的所有成员名称都与未定义的值关联,则定义为 (name, value) 对的关联数组的变量被视为未定义。

2.4. Value Modifiers (值修饰符)

Level 4模板表达式中的每个变量都可以具有修饰符,指示其扩展限于变量值字符串的前缀,或者其扩展作为值列表或 (name, value) 对的关联数组形式的复合值展开。

modifier-level4 =  prefix / explode

2.4.1. Prefix Values (前缀值)

前缀修饰符 (Prefix Modifier) 表示变量扩展限于变量值字符串的前缀。前缀修饰符通常用于分层划分标识符空间,这在参考索引和基于哈希的存储中很常见。它还用于将扩展值限制为最大字符数。前缀修饰符不适用于具有复合值的变量。

prefix        =  ":" max-length
max-length = %x31-39 0*3DIGIT ; 正整数 < 10000

max-length 是一个正整数,指的是变量值作为Unicode字符串从头开始的最大字符数。请注意,这个编号是以字符为单位的,而不是八位字节,以避免在多八位字节编码字符的八位字节之间或百分号编码三元组内分割。如果 max-length 大于变量值的长度,则使用整个值字符串。

例如:

给定变量赋值

var := "value"
semi := ";"

示例模板 扩展

{var} value
{var:20} value
{var:3} val
{semi} %3B
{semi:2} %3B

2.4.2. Composite Values (复合值)

展开修饰符 (Explode Modifier) ("*") 表示变量将被视为由值列表或 (name, value) 对的关联数组组成的复合值。因此,扩展过程应用于复合的每个成员,就好像它被列为单独的变量一样。这种类型的变量规格符的自文档化程度明显低于非展开变量,因为变量名与扩展后URI引用的显示方式之间的对应关系较少。

explode       =  "*"

由于URI模板不包含类型或模式的指示,因此假定展开变量的类型由上下文确定。例如,处理器可能以区分字符串、列表或关联数组的形式提供值。同样,使用模板的上下文(脚本、标记语言、接口定义语言等)可能定义将变量名与类型、结构或模式关联的规则。

展开修饰符提高了URI模板语法的简洁性。例如,为给定街道地址提供地理地图的资源可能接受数百个地址输入字段的排列,包括部分地址(例如,仅城市或邮政编码)。这样的资源可以描述为按顺序列出每个地址组件的模板,或者使用展开修饰符的更简单的模板,如:

/mapper{?address*}

以及一些定义名为 "address" 的变量可以包含什么的上下文,例如通过引用某些其他地址标准(例如 [UPU-S42])。了解模式的接收者可以提供适当的扩展,例如:

/mapper?city=Newport%20Beach&state=CA

展开变量的扩展过程取决于所使用的运算符以及复合值是被视为值列表还是 (name, value) 对的关联数组。结构被处理为关联数组,名称对应于结构定义中的字段,并使用 "." 分隔符指示子结构中的名称层次结构。

如果变量具有复合结构,并且该结构中只有某些字段具有已定义的值,则扩展中仅存在已定义的对。这对于由大量潜在查询项组成的模板很有用。

应用于列表变量的展开修饰符会导致扩展根据运算符重复该变量的扩展,每个列表成员一次。