メインコンテンツまでスキップ

3. Expansion (展開)

URIテンプレート展開のプロセスは、テンプレート文字列を最初から最後までスキャンし、リテラル文字をコピーし、各式を式の演算子を式内で名前が付けられた各変数の値に適用した結果で置き換えることです。各変数の値は、テンプレート展開前に形成されなければなりません (MUST)。

本セクションでは、URIテンプレート文法の各側面に対する展開の要件を定義します。展開プロセス全体の非規範的なアルゴリズムは付録Aで提供されています。

テンプレートプロセッサが式の外側で <URI-Template> 文法に一致しない文字シーケンスに遭遇した場合、テンプレートの処理を停止すべきであり (SHOULD)、URI参照結果はテンプレートの展開された部分の後に未展開の残りを含むべきであり (SHOULD)、エラーの位置とタイプを呼び出し元アプリケーションに示すべきです (SHOULD)。

式内でエラーに遭遇した場合、例えばテンプレートプロセッサが認識しない、またはまだサポートしていない演算子または値修飾子、あるいは <expression> 文法で許可されていない文字が見つかった場合、式の未処理部分は未展開のまま結果にコピーされるべきであり (SHOULD)、テンプレートの残りの処理は続行されるべきであり (SHOULD)、エラーの位置とタイプを呼び出し元アプリケーションに示すべきです (SHOULD)。

エラーが発生した場合、返される結果は有効なURI参照ではない可能性があります。これは診断目的でのみ意図された、不完全に展開されたテンプレート文字列になります。

3.1. Literal Expansion (リテラル展開)

リテラル文字がURI構文のどこでも許可されている場合 (unreserved / reserved / pct-encoded)、それは結果文字列に直接コピーされます。そうでない場合、リテラル文字のパーセントエンコードされた等価物が結果文字列にコピーされます。これは、まず文字をUTF-8でのオクテットシーケンスとしてエンコードし、次に各オクテットをパーセントエンコードされたトリプレットとしてエンコードすることによって行われます。

3.2. Expression Expansion (式展開)

各式は開き中括弧 (") 文字で示され、次の閉じ中括弧 (") まで続きます。式はネストできません。

式の展開は、その式タイプを決定し、式内の各カンマ区切りのvarspecに対してそのタイプの展開プロセスに従うことによって行われます。Level 1テンプレートは、デフォルト演算子(単純な文字列値展開)と式ごとに単一の変数に制限されています。Level 2テンプレートは、式ごとに単一のvarspecに制限されています。

式タイプは、開き中括弧の後の最初の文字を調べることによって決定されます。文字が演算子である場合、後の展開決定のためにその演算子に関連付けられた式タイプを記憶し、変数リストの次の文字にスキップします。最初の文字が演算子でない場合、式タイプは単純な文字列展開であり、最初の文字は変数リストの始まりです。

以下のサブセクションの例では、次の変数値定義を使用します:

count := ("one", "two", "three")
dom := ("example", "com")
dub := "me/too"
hello := "Hello World!"
half := "50%"
var := "value"
who := "fred"
base := "http://example.com/home/"
path := "/foo/bar"
list := ("red", "green", "blue")
keys := [("semi",";"),("dot","."),("comma",",")]
v := "6"
x := "1024"
y := "768"
empty := ""
empty_keys := []
undef := null

3.2.1. Variable Expansion (変数展開)

未定義 (セクション2.3) の変数は値を持たず、展開プロセスによって無視されます。式内のすべての変数が未定義の場合、式の展開は空文字列になります。

定義された非空の値の変数展開は、許可されたURI文字のサブストリングを生成します。セクション1.6で説明されているように、展開プロセスはUnicodeコードポイントの観点から定義されており、結果のURI参照で非ASCII文字が一貫してパーセントエンコードされることを保証します。テンプレートプロセッサが一貫した展開を得る1つの方法は、値文字列をUTF-8にトランスコードし(まだUTF-8でない場合)、許可されたセット内にない各オクテットを対応するパーセントエンコードされたトリプレットに変換することです。

特定の展開に対する許可されたセットは式タイプに依存します:予約済み ("+") およびフラグメント ("#") 展開は、(unreserved / reserved / pct-encoded) の和集合の文字セットをパーセントエンコードなしで通過させることを許可しますが、他のすべての式タイプは、パーセントエンコードなしで通過できる文字を非予約文字のみに制限します。パーセント文字 ("%") は、パーセントエンコードされたトリプレットの一部としてのみ許可され、予約済み/フラグメント展開の場合のみです:他のすべてのケースでは、値文字 "%" は変数展開によって "%25" としてパーセントエンコードされなければなりません (MUST)。

変数が式内で複数回、またはURIテンプレートの複数の式内で出現する場合、その変数の値は展開プロセス全体を通じて静的のままでなければなりません (MUST)(つまり、各展開を計算する目的で変数は同じ値を持つ必要があります)。ただし、予約文字またはパーセントエンコードされたトリプレットが値に出現する場合、一部の式タイプではパーセントエンコードされ、他の式タイプではパーセントエンコードされません。

単純な文字列値の変数の場合、展開はエンコードされた値を結果文字列に追加することで構成されます。爆発修飾子は効果がありません。プレフィックス修飾子は、展開をデコードされた値の最初のmax-length文字に制限します。値にマルチオクテットまたはパーセントエンコードされた文字が含まれている場合、文字の途中で値を分割しないように注意する必要があります:各Unicodeコードポイントを1文字としてカウントします。

連想配列の変数の場合、展開は式タイプと爆発修飾子の存在の両方に依存します。爆発修飾子がない場合、展開は定義された値を持つ各 (name, value) ペアのカンマ区切りの連結を追加することで構成されます。爆発修飾子がある場合、展開は定義された値を持つ各ペアを "name=value" として、または値が空文字列で式タイプがフォームスタイルパラメータを示さない場合(つまり、"?" または "&" タイプでない場合)、単に "name" として追加することで構成されます。nameとvalue文字列の両方は、単純な文字列値と同じ方法でエンコードされます。定義されたペア間には、次の表で定義されている式タイプに従って、セパレータ文字列が追加されます:

タイプ   セパレータ
"," (デフォルト)
+ ","
# ","
. "."
/ "/"
; ";"
? "&"
& "&"

リスト値の変数の場合、爆発修飾子がない場合、展開は定義された値を持つ各リストメンバー値のカンマ区切りの連結をその変数の単一名の値として追加することで構成されます。爆発修飾子がある場合、展開は定義された値を持つ各リストメンバー値をその変数名を持つ個別の値として追加するか、名前付き変数を持たない式タイプ(";"、"?"、または "&" なし)の場合、各値をタイプ固有のセパレータで区切って追加することで構成されます。

リスト値または連想配列値のプレフィックス修飾子は効果がありません。

3.2.2. Simple String Expansion: {var} (単純文字列展開)

演算子が指定されていない場合、単純文字列展開がデフォルトの式タイプです。

変数リスト内の定義された各変数に対して、セクション3.2.1で定義されているように変数展開を実行し、許可される文字は非予約セットの文字です。複数の変数が定義された値を持つ場合、カンマ (",") を変数展開間のセパレータとして結果文字列に追加します。

例テンプレート         展開結果

{var} value
{hello} Hello%20World%21
{half} 50%25
O{empty}X OX
O{undef}X OX
{x,y} 1024,768
{x,hello,y} 1024,Hello%20World%21,768
?{x,empty} ?1024,
?{x,undef} ?1024
?{undef,y} ?768
{var:3} val
{var:30} value
{list} red,green,blue
{list*} red,green,blue
{keys} semi,%3B,dot,.,comma,%2C
{keys*} semi=%3B,dot=.,comma=%2C

3.2.3. Reserved Expansion: {+var} (予約済み展開)

予約済み展開は、Level 2以上のテンプレートのプラス ("+") 演算子で示され、単純文字列展開と同じですが、置換される値にもパーセントエンコードされたトリプレットと予約済みセットの文字が含まれる可能性があります。

変数リスト内の定義された各変数に対して、セクション3.2.1で定義されているように変数展開を実行し、許可される文字は (unreserved / reserved / pct-encoded) セットの文字です。複数の変数が定義された値を持つ場合、カンマ (",") を変数展開間のセパレータとして結果文字列に追加します。

例テンプレート              展開結果

{+var} value
{+hello} Hello%20World!
{+half} 50%25

{base}index http%3A%2F%2Fexample.com%2Fhome%2Findex
{+base}index http://example.com/home/index
O{+empty}X OX
O{+undef}X OX

{+path}/here /foo/bar/here
here?ref={+path} here?ref=/foo/bar
{+x,hello,y} 1024,Hello%20World!,768
{+path,x}/here /foo/bar,1024/here
{+path:6}/here /foo/b,1024/here
{+list} red,green,blue
{+list*} red,green,blue
{+keys} semi,;,dot,.,comma,,
{+keys*} semi=;,dot=.,comma=,

3.2.4. Fragment Expansion: \{#var} (フラグメント展開)

フラグメント展開は、Level 2以上のテンプレートのクロスハッシュ ("#") 演算子で示され、予約済み展開と同じですが、いずれかの変数が定義されている場合、最初にクロスハッシュ文字(フラグメント区切り文字)が結果文字列に追加されます。

例テンプレート         展開結果

{#var} #value
{#hello} #Hello%20World!
{#half} #50%25
foo{#empty} foo#
foo{#undef} foo
{#x,hello,y} #1024,Hello%20World!,768
{#path,x}/here #/foo/bar,1024/here
{#path:6}/here #/foo/b/here
{#list} #red,green,blue
{#list*} #red,green,blue
{#keys} #semi,;,dot,.,comma,,
{#keys*} #semi=;,dot=.,comma=,

3.2.5. Label Expansion with Dot-Prefix: {.var} (ドット接頭辞付きラベル展開)

ラベル展開は、Level 3以上のテンプレートのドット (".") 演算子で示され、異なるドメイン名またはパスセレクター(例:ファイル拡張子)を持つURIスペースを記述するのに役立ちます。

変数リスト内の定義された各変数に対して、"." を結果文字列に追加し、次にセクション3.2.1で定義されているように変数展開を実行し、許可される文字は非予約セットの文字です。

"." は非予約セットに含まれているため、"." を含む値は複数のラベルを追加する効果があります。

例テンプレート         展開結果

{.who} .fred
{.who,who} .fred.fred
{.half,who} .50%25.fred
www{.dom*} www.example.com
X{.var} X.value
X{.empty} X.
X{.undef} X
X{.var:3} X.val
X{.list} X.red,green,blue
X{.list*} X.red.green.blue
X{.keys} X.semi,%3B,dot,.,comma,%2C
X{.keys*} X.semi=%3B.dot=..comma=%2C
X{.empty_keys} X
X{.empty_keys*} X

3.2.6. Path Segment Expansion: {/var} (パスセグメント展開)

パスセグメント展開は、Level 3以上のテンプレートのスラッシュ ("/") 演算子で示され、URIパス階層を記述するのに役立ちます。

変数リスト内の定義された各変数に対して、"/" を結果文字列に追加し、次にセクション3.2.1で定義されているように変数展開を実行し、許可される文字は非予約セットの文字です。

パスセグメント展開の展開プロセスは、"." の代わりに "/" を置換することを除いて、ラベル展開と同じです。ただし、"." とは異なり、"/" は予約文字であり、値に見つかった場合はパーセントエンコードされます。

例テンプレート         展開結果

{/who} /fred
{/who,who} /fred/fred
{/half,who} /50%25/fred
{/who,dub} /fred/me%2Ftoo
{/var} /value
{/var,empty} /value/
{/var,undef} /value
{/var,x}/here /value/1024/here
{/var:1,var} /v/value
{/list} /red,green,blue
{/list*} /red/green/blue
{/list*,path:4} /red/green/blue/%2Ffoo
{/keys} /semi,%3B,dot,.,comma,%2C
{/keys*} /semi=%3B/dot=./comma=%2C

3.2.7. Path-Style Parameter Expansion: {;var} (パススタイルパラメータ展開)

パススタイルパラメータ展開は、Level 3以上のテンプレートのセミコロン (";") 演算子で示され、"path;property" や "path;name=value" などのURIパスパラメータを記述するのに役立ちます。

変数リスト内の定義された各変数に対して:

  • ";" を結果文字列に追加します;
  • 変数が単純な文字列値を持つか、爆発修飾子が指定されていない場合:
    • 変数名(リテラル文字列としてエンコード)を結果文字列に追加します;
    • 変数の値が空でない場合、"=" を結果文字列に追加します;
  • セクション3.2.1で定義されているように変数展開を実行し、許可される文字は非予約セットの文字です。
例テンプレート         展開結果

{;who} ;who=fred
{;half} ;half=50%25
{;empty} ;empty
{;v,empty,who} ;v=6;empty;who=fred
{;v,bar,who} ;v=6;who=fred
{;x,y} ;x=1024;y=768
{;x,y,empty} ;x=1024;y=768;empty
{;x,y,undef} ;x=1024;y=768
{;hello:5} ;hello=Hello
{;list} ;list=red,green,blue
{;list*} ;list=red;list=green;list=blue
{;keys} ;keys=semi,%3B,dot,.,comma,%2C
{;keys*} ;semi=%3B;dot=.;comma=%2C

3.2.8. Form-Style Query Expansion: {?var} (フォームスタイルクエリ展開)

フォームスタイルクエリ展開は、Level 3以上のテンプレートのクエスチョンマーク ("?") 演算子で示され、全体のオプションのクエリコンポーネントを記述するのに役立ちます。

変数リスト内の定義された各変数に対して:

  • これが最初の定義された値である場合は "?" を結果文字列に追加し、それ以降は "&" を追加します;
  • 変数が単純な文字列値を持つか、爆発修飾子が指定されていない場合、変数名(リテラル文字列としてエンコード)と等号文字 ("=") を結果文字列に追加します;そして、
  • セクション3.2.1で定義されているように変数展開を実行し、許可される文字は非予約セットの文字です。
例テンプレート         展開結果

{?who} ?who=fred
{?half} ?half=50%25
{?x,y} ?x=1024&y=768
{?x,y,empty} ?x=1024&y=768&empty=
{?x,y,undef} ?x=1024&y=768
{?var:3} ?var=val
{?list} ?list=red,green,blue
{?list*} ?list=red&list=green&list=blue
{?keys} ?keys=semi,%3B,dot,.,comma,%2C
{?keys*} ?semi=%3B&dot=.&comma=%2C

3.2.9. Form-Style Query Continuation: {&var} (フォームスタイルクエリ継続)

フォームスタイルクエリ継続は、Level 3以上のテンプレートのアンパサンド ("&") 演算子で示され、固定パラメータを持つリテラルクエリコンポーネントを既に含むテンプレート内でオプションの &name=value ペアを記述するのに役立ちます。

変数リスト内の定義された各変数に対して:

  • "&" を結果文字列に追加します;
  • 変数が単純な文字列値を持つか、爆発修飾子が指定されていない場合、変数名(リテラル文字列としてエンコード)と等号文字 ("=") を結果文字列に追加します;そして、
  • セクション3.2.1で定義されているように変数展開を実行し、許可される文字は非予約セットの文字です。
例テンプレート         展開結果

{&who} &who=fred
{&half} &half=50%25
?fixed=yes{&x} ?fixed=yes&x=1024
{&x,y,empty} &x=1024&y=768&empty=
{&x,y,undef} &x=1024&y=768

{&var:3} &var=val
{&list} &list=red,green,blue
{&list*} &list=red&list=green&list=blue
{&keys} &keys=semi,%3B,dot,.,comma,%2C
{&keys*} &semi=%3B&dot=.&comma=%2C