Skip to main content

2. Syntax (语法)

URI Template (URI模板) 是一个可打印Unicode字符的字符串,包含零个或多个嵌入的变量表达式,每个表达式由一对匹配的大括号('{', '}')分隔。

URI-Template  =  *( literals / expression )

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

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模板的参数化部分。每个表达式包含一个可选的操作符,它定义了表达式类型及其相应的扩展过程,后跟一个逗号分隔的变量说明符列表(变量名称和可选值修饰符)。如果未提供操作符,则表达式默认为未保留值的简单变量扩展。

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

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

  • + 保留字符串;
  • # 以"#"为前缀的片段标识符;
  • . 以"."为前缀的名称标签或扩展名;
  • / 以"/"为前缀的路径段;
  • ; 以";"为前缀的路径参数名称或name=value对;
  • ? 以"?"开头的查询组件,由"&"分隔的name=value对组成;以及,
  • & 在字面查询组件内继续查询样式的&name=value对。

操作符字符等号("=")、逗号(",")、感叹号("!")、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可能包含一个或多个百分号编码的三元组。这些三元组被视为变量名称的基本部分,在处理期间不会被解码。包含百分号编码字符的varname与解码了这些相同字符的varname不是同一个变量。提供URI模板的应用程序预期在变量名称中使用百分号编码时保持一致。

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

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

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

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

2.4. Value Modifiers (值修饰符)

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

modifier-level4  =  prefix / explode

2.4.1. Prefix Values (前缀值)

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

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

explode       =  "*"

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

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

/mapper{?address*}

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

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

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

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

应用于列表变量的explode修饰符会导致扩展迭代列表的成员值。对于路径和查询参数扩展,每个成员值与变量名称配对作为(varname, value)对。这允许对多个值重复路径和查询参数,如:

给定变量赋值:

year := ("1965", "2000", "2012")
dom := ("example", "com")

示例模板与扩展:

find{?year*}    find?year=1965&year=2000&year=2012
www{.dom*} www.example.com