

[1] [[SGML]] における[[空白]]の取扱いや[[正規化]],
周辺事項について。

[[XML//空白]]もあわせて参照されたい。
また、例示は[[規格参照具象構文]]又は [[XML]]
と同じ[[具象構文]]を想定する。

また、ここで「空白」はなんとなくそれっぽい意味(謎)で曖昧に使います。
(詳しい意味は抽象構文・具象構文によりますが、
大体の場合は [CODE(ABNF)[[[SPACE]] / [[RS]] / [[RE]] / [[SEPCHAR]]]] ≒ [CODE(ABNF)[[[SP]] / [[TAB]] / [[CR]] / [[LF]]]] と考えて良いでしょう。)
「[[間隔]]」は、[[文字]] [CODE(char)[SPACE]] を指します。
[WEAK[[[WebSGML]] では、まさに [CODE(ABNF)[[DFN[空白]] = [[SPACE]] / [[RS]] / [[RE]] / [[SEPCHAR]]]] です。 (K.2.4.2)]]

括弧内の番号などは、 [[JISX4151]] の該当部分です。

[[#comment]]


* 無視される空白

[2] [[分離子]] [CODE(SGML)[[[s]]]] 
([CODE(ABNF)[= SPACE / RE / RS / SEPCHAR ;; (5) ]]) は無視されます。 (5.2.1)

つまり、
- [[文書要素]]の外で、他の[[マーク]]の一部ではない空白
- [[タグ]]の中で、[[属性値表記]]の一部ではない空白
- [[内容モデル]]が[[要素内容]]である要素内の空白
-- [WEAK[例えば、 [[HTML]] の [CODE(HTML)[[[head]]]] 要素の内容であって、子要素・子マークの一部ではない空白。]]
-- ?? マークの最小化の影響で一見これに該当しても無視されない (データタグとかになる) 空白はあり得るか否か?
- [[現対応表]]によって対応付けされておらず、
区切子として認知できるもの (8.4.6)

は無視されます。

[3] [[内容]]の中で、 ([[ISO8879]] 7.6.1, JIS 6.6.1, 参考 3 3.3.3 も参照。)
- [CODE(SGML)[RS]] はマークとして解釈できなければ無視する。
- すべての参照の置換・マークの認知の後に残る [CODE(SGML)[RE]] は、
== 要素の最初の [CODE(SGML)[RE]] は、その直前に [CODE(SGML)[RS]], [[データ]]又は[[真の部分要素]]がなければ、無視する。
--- [SAMP(SGML)[<e>[CODE(SGML)[RE]]foo</e>]] -> [SAMP[foo]]
--- [SAMP(SGML)[<e>[CODE(SGML)[RS]][CODE(SGML)[RE]]foo</e>]] -> [SAMP[[CODE(SGML)[RS]][CODE(SGML)[RE]]foo]] -> [SAMP[[CODE(SGML)[RE]]foo]]
--- [SAMP(SGML)[<e>data[CODE(SGML)[RE]]foo</e>]] -> [SAMP[data[CODE(SGML)[RE]]foo]]
--- [SAMP(SGML)[<e><pSub/>[CODE(SGML)[RE]]foo</e>]] -> [SAMP[<pSub/>[CODE(SGML)[RE]]foo]]
--- [SAMP(SGML)[<e><add/>[CODE(SGML)[RE]]foo</e>]] -> [SAMP[foo]]
--- [SAMP(SGML)[<e><!>[CODE(SGML)[RE]]foo</e>]] -> [SAMP[<!>foo]]
== 要素の最後の [CODE(SGML)[RE]] は、その直後にデータ又は真の部分要素がなければ、無視する。
== [CODE(SGML)[RS]] 又は [CODE(SGML)[RE]] の直後に位置しない [CODE(SGML)[RE]] は、その前にデータ又は真の部分要素がなければ、無視する。
--- [SAMP(SGML)[foo[CODE(SGML)[RE]]bar]] -> [SAMP[foo[CODE(SGML)[RE]]bar]]
--- [SAMP(SGML)[<!>[CODE(SGML)[RE]]<!>[CODE(SGML)[RE]]bar]] -> [SAMP[bar]]
--- [SAMP(SGML)[<e><pSub/>[CODE(SGML)[RE]][CODE(SGML)[RE]]foo</e>]] -> [SAMP[<pSub/>[CODE(SGML)[RE]][CODE(SGML)[RE]]foo]]
--- [SAMP(SGML)[<e>[CODE(SGML)[RE]][CODE(SGML)[RE]]foo</e>]] -> [SAMP[foo]]
== 以上に該当しない場合は、データとする。
-- [4]

> [CODE(SGML)[RE]] をデータとするかどうかの判定は、
マークの認知の過程で行う。マークの認知に、
タグの省略の認知を含めて、 (1)〜(3)に従って
[CODE(SGML)[RE]] か無視できるかどうかの判定に先立って行う。
この手順では、
[PRE[
  (quote | #PCDATA)*
]PRE]

のように、要素の内容のどこにでもデータが現れ得る通常の場合、
直感に合った結果が得られる。しかしながら、
[PRE[
  (x, #PCDATA)
]PRE]

のように、内容モデルがデータの現れ得る位置に制限を課す場合には、
(1)又は(2)の状況がマークの認知の最中に誤りとなることがある。
このような内容モデルは、通常必要としないので、推奨しない
(10.2.4 参照)。

[5] >>3 の例 (JIS X 4151 より):
[PRE[
[CODE(SGML)[RS[INS[[SUB[1]]]]]] record 1 <outer><sub> [CODE(SGML)[RE[INS[[SUB[1]]]]]]
[CODE(SGML)[RS[INS[[SUB[2]]]]]] record 2 </sub> [CODE(SGML)[RE[INS[[SUB[2]]]]]]
[CODE(SGML)[RS[INS[[SUB[3]]]]]] </outer> record 3 [CODE(SGML)[RE[INS[[SUB[3]]]]]]
]PRE]

で、要素 [SAMP(SGML)[outer]] について考える。
[CODE(SGML)[RE[INS[[SUB[1]]]]]] 及び
[CODE(SGML)[RS[INS[[SUB[2]]]]]] は子要素内にあるので、
ここでは考えないことになる。従って、
[CODE(SGML)[RE[INS[[SUB[2]]]]]] が内容の最初の
[CODE(SGML)[RE]] である。

さて、 [SAMP(SGML)[sub]] が真の部分要素であるなら、
この [CODE(SGML)[RE[INS[[SUB[2]]]]]] はデータとなるが、
[[添加要素]]であれば、前にデータも真の部分要素も無いので、
無視される。

要素 [SAMP(SGML)[sub]] について、最初の [CODE(SGML)[RE]]
は [CODE(SGML)[RE[INS[[SUB[1]]]]]] である。
その前にはデータも真の部分要素も無いので、無視する。

[6] 添加要素とか真の部分要素とか、なんでこんなややこしい規則があるんだろう?

[21] >>6 参考3 3.3.1 参照。それっぽいことが書いてある。
(処理指令だけの[[記録]]を無視するとか。)

[7] >>3 の続き。 [CODE(SGML)[RE]] は、それに続く最初のデータ又は真の部分要素の直前に位置するものとして扱います。
つまり、その間に他のマークがある場合、その後に位置するものとします。
ずなわち、 [SAMP(SGML)[<e>foo[CODE(SGML)[RE]]<!>bar</e>]] -> [SAMP[foo<!>[CODE(SGML)[RE]]bar]],
[SAMP(SGML)[<e>foo[CODE(SGML)[RE]]<add/>bar</e>]] -> [SAMP[foo<add/>[CODE(SGML)[RE]]bar]]。
[WEAK[(なんでこんな面倒な規則があるんだろう?)]]

[22] 参考3 3.3.1 の例で、
[PRE[
<p>
最初のデータ
<?処理指令1>
<?処理指令2>
最後のデータ
</p>
]PRE]

と
[PRE[
<p>最初のデータ
<?処理指令1><?処理指令2>最後のデータ</p>
]PRE]

は同値って書いてある。で、 >>7 によれば更に
[PRE[
<p>最初のデータ<?処理指令1><?処理指令2>
最後のデータ</p>
]PRE]

と同値と解釈されるのか?

[8] なお、 >>3-8 で、「データ」として扱うのは通常の意味のデータのほかに、
[[特定文字データ実体]], [[非SGML実体]], [[SGML部分文書実体]]も含んでいます。[WEAK[[[処理指令実体]]は含みません。]]
[WEAK[これについては直感とおおむね一致する動作でしょう。]]

[9] [CODE(SGML)[[[参照終了]]]]である [CODE(SGML)[RE]]
は無視されます (8.4.5)。例えば、
[PRE[
<e>&ref[CODE(SGML)[RE]]
[CODE(SGML)[RS]]non-ref</e>
]PRE]

→ [SAMP[[VAR[ref]]non-ref]]

[26] このわけのわかんない複雑な規則は、
[[WebSGML]] で [CODE(SGML)[[[KEEPRSRE]] YES]]
にしている場合には適用されません。
[[混合内容]]中の全ての[[空白]]は、
[[データ文字節]]として[[グローブ]]中に含まれ、
[[要素内容]]中の全ての空白は、
[[s分離子節]]としてグローブ中に含まれます。
(K.3.8.2 参照。)

[[#comment]]


* マーク最小化と空白

[3] [[データタグ雛形]]と[[内容]]との照合は、その内容の 
[[マーク]]の[[認知]]及び[[参照]]の[[解決]]を行った後で、
[CODE(SGML)[RS]] および [CODE(SGML)[RE]]
を無視する前に行います。
(6.3.2)

[[#comment]]


* 表記の中の空白と正規化

- [[属性値//正規化]]
- [[最小表記]]

[18] [[引数表記]]には、それ自体には空白と正規化についての規定はありません。

[[#comment]]


* 実体参照・文字参照

[15] [[文字参照]]には[[数値文字参照]]と[[名前文字参照]]があります。
前者は常に[[データ]]として、後者は生の文字と同等として扱われます。 (8.5)

例えば、 [SAMP(SGML)[&ref&#RE;]] と 
[SAMP(SGML)[&ref[CODE(SGML)[RE]]]]
は同値で、 [SAMP(SGML)[&ref;]] とほぼ同じ意味です。
一方、 [SAMP(SGML)[&ref&#13;]] は
[SAMP(SGML)[&ref;&#13;]] と同値で、後半は SGML
的な意味を持たない単なる文字 [CODE[0x0D]] です。

[28]
名前文字参照は生の文字と同等に[[機能文字]]として解釈されますが、
[[区切子]]の先頭以外を名前文字参照で表すことはできません。
([[名無しさん]])


[29]
ですから、空白を含む短縮参照の途中に文字参照を使うことも、東漸できません。 ([CODE(SGML)[[[nero]]]] の直前で区切れがあると見なされるはずです。)
もっとも、短縮参照の一部を文字参照で表そうとするのは普通では考えられないです。
([[名無しさん]])


[[#comment]]


** 短縮参照と空白

[12] [[短縮参照]]について (8.4.6)。
- 短縮参照が[[現対応表]]により[[一般実体]]に対応付けてある場合には一般実体に置換しますが、そうでない場合には、
-- 区切子として認知できるなら、分離子 [CODE(SGML)[s]] とみなし、結果無視します (>>2)。
-- できないなら、データとして扱います。

[13] 8.4.6.1 では、[DFN[同値な参照列]]が規定されています。
短縮参照を[[名前実体参照]]に置換する必要がある時に、
[[記録]]が長くなり過ぎないようにするための措置らしいです。
,短縮参照に含まれるか否か	,==	,同値な参照列
,[CODE(SGML)[RS]]	,[CODE(SGML)[RE]]	,
,×	,×	,[CODE(ABNF)[[[ero]] [[名前]] [[refc]]]]
,○	,×	,[CODE(ABNF)[RS ero [[名前]] refc]]
,×	,○	,[CODE(ABNF)[ero [[名前]] RE]]
,○	,○	,[CODE(ABNF)[RS ero [[名前]] RE]]

内容の [CODE(SGML)[RS]] は無視されるし参照終了の
[CODE(SGML)[RE]] もデータにならないので本当に同値で、
この変換は影響が無いそうです。

[14] で、次の例でも影響が無いんでしょうか?
[PRE[
<!ENTITY ref "&#RE;something">
 [INS[...]]
<e>[VAR[&#RS;&ref;]]foo</e>
<!-- ここで、 [VAR[&#RS;&ref;]] はそれと同値な
     ''短縮参照''とします。 -->
]PRE]

う〜ん。。。

[16] 短縮参照の定義では特殊な文字列として[[B列]]があります。
その中では文字 [CODE(SGML)[B]] が1つの空白に対応します。
詳しくは[[短縮参照]]を参照。 (8.6.5)

[[#comment]]


* 内容中の空白の保持 — Web SGML

[24] [[WebSGML]] K.3.8.2 では、新しい[[他機能]]
[CODE(SGML)[[[KEEPRSRE]]]] を定義しています。

[[SGML宣言]]でこの機能を [CODE(SGML)[YES]]
にすると、 [[ISO8879]]:1986 7.6.1 == JIS X 4151‐1992
6.6.1 == >>3,>>7 は無視されます。
つまり、[[混合内容]]中の全ての空白は、[[データ文字節]]として[[グローブ]]に含まれ、
[[要素内容]]中の全ての空白は、 [[s分離子節]]としてグローブに含まれます。

なお、この機能が影響するのは要素内容の空白だけです。
属性値表記などでの規則は変化しません。

[25] [[XML]] の [CODE(XML)[[[xml]]:[[space]]]]
辺りとこの機能が関連しているといえます。

[27]
>>25 XML は常に [CODE(SGML)[KEEPRSRE YES]]
で、 [CODE(XMLa)[xml:space]] は単に[[応用]]水準の情報 (構文解析には関係しない) ですから、直接は関係ないですね。 
([[名無しさん]])

[[#comment]]


* メモ

[FIG[ [10] [[Web SGML]]
>
:K.2.4.2 空白 (white space):
[CODE(SGML)[[[SEPCHAR]]]], [CODE(SGML)[[[SPACE]]]],
[CODE(SGML)[[[RE]]]] 及び [CODE(SGML)[[[RS]]]]
の各[[機能]]に割り当てられた[[文字]]。
]FIG]


[30] [CITE[IRC logs: freenode / #whatwg / 20130221]]
( ([TIME[2013-02-26 21:20:52 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20130221>

[11] [CITE@en[Breaking: stop treating alpha and alphanumeric as mass nouns]]
([[annevk]]著, [TIME[2017-02-04 03:52:58 +09:00]])
<https://github.com/whatwg/infra/commit/4707bf7b3d8b5b6314ee3dabd29856011eebbb00>