[1] XML の実体参照をどう扱うかについて。 (仕様書の <http://www.w3.org/TR/REC-xml#entproc> の辺り。)
種類 | パラ | 内解 | 外解 | 外非 | 文字 |
内容中の参照 | 認知されない | 取込む | 妥当性を検証するなら取込む | 禁止 | 取込む |
属性値中の参照 | 認知されない | 表記中に取込む | 禁止 | 取込む | |
属性値として出現 | 認知されない | 禁止 | 通知 | 認知されない | |
実体値中の参照 | 表記中に取込む | 処理しない | 誤り | 取込む | |
DTD 中の参照 | PE として取込む | 禁止 | 禁止 |
ENTITY
又は ENTITIES
である属性値。 (実体参照ではない。名前そのもの。)IGNORE
区間内の参照 (に見えるもの) は解釈されない。standalone="yes" の時には、その後の要素型宣言や属性並び宣言も処理しなければなりません。そうでないときは逆に処理してはなりません。 <http://www.w3.org/TR/REC-xml#dt-use-mdecl>
[4] ある実体の置換文が取り出されて処理され、 参照のある場所にそれがそもそも存在していたようにされる時、 これを実体を取り込むといいます。 置換文は文字データやマークなどを含むことが出来て、 普通の方法で処理されます。 文字参照はその参照の場所で指示された文字が処理される時取り込まれます。
例えば、 <!ENTITY ATandT "AT&T"> ... <p>昔々あるところに、&ATandT; という(ry</p> 文書片で、 p 要素の内容は 昔々あるところに、AT&T という(ry になります。
[9] 実体参照が属性値表記中に出現する時、 或いはパラメーター実体参照が表記実体値中に出現する時、 その置換文はその参照の代わりに、 参照が認知された場所に最初から文書の一部として存在していたように処理します。 但し、置換文中の一重又は二重引用符は常に普通のデータ文字として扱い、 表記の終端とはしません。
[10] XML の仕様書の >>9 の説明はちょっと分かりにくいです。 SGML にいい例があります (JISX4151‐1992 6.2.2)。
<!ENTITY % bullet "o"> <!ENTITY prefix "%bullet;"> <!-- この参照「%bullet;」は、「prefix」の宣言のときに その実体に書き換わる。実体「prefix」を参照するたびに 書き換わるのではない。 -->
[13] DTD 中のパラメーター実体 (実体値中を除く。)
は、妥当性を検証するなら取込みます。
この時、置換文の最初と最後に SP
が付加されます。
[14] 例えば、
<!ENTITY % name "ELEMENT"> <!ELEMENT%name;ANY>
は意図したように (<!ELEMENT ELEMENT ANY> として) 解釈されます。
SP
を補う) って、 SGML にはないですよね? 確かに >>14 のような記述は SGML でも妥当ですが、それはそもそもそう定義されているからであって、間隔が補われるからではないですよね。ps
, ds
でほぼ (完全にではないけど) 引数実体参照の出現可能な場所を構文上明示しているけど、 XML ではそれをやってない関係なのかなあ。ps
にしか書けません。) (整形式制約 <http://www.w3.org/TR/REC-xml#wfc-PEinInternalSubset>)[12] 実体値中の内部解析一般実体への参照は、 処理されずにそのまま素通りします。 実際にその参照を含む実体が参照された時に参照された場所で解決されます。
<!ENTITY a "A"> <!ENTITY ka "K&a;"> ... <foo>&ka;</foo>
foo 要素の内容は ka で、参照を解いて Ka, まだ参照があるので解いて KA, 参照がなくなったのでこれが最終的な内容になります。
<!ENTITY % inner "- an & entity --"> <!ENTITY outer "AN %inner; ENTITY"> ... <foo>AN &outer; ELEMENT</foo>
この例で foo の内容は意図したとおり AN AN - an & entity -- ENTITY ELEMENT になります。 うっかり気を遣って <!ENTITY % inner "- an &amp; entity --"> としてしまうと、本当に AN AN - an & entity -- ENTITY ELEMENT になってしまいます。
[17] SGML では、そもそも (XML でいう)
実体値中で一般実体参照は使えません。単なる
&
で始まる文字列として扱うようです。
(引数表記
内で ero
を認知しません。)
XML では追加制限として実体値中で文字参照でも一般文字参照でもない単独の文字
&
を使うことが出来ませんから、
このような表現になっているようです。
[3] パラメーター(引数)実体参照は、 DTD
の認められた場所でのみ使用できます。
(ATTLIST
宣言の属性の既定値指定中では使えません。)
それ以外の場所では、単に %
で始まる文字の列として扱われます。
例えば、 <foo attr="%name;">%aiueo;</foo>
の foo 要素の内容は文字列 %aiueo;
で、同要素の attr
属性の値は文字列
%name; になります。
また、型が ENTITY
又は ENTITIES
である属性の値において数値文字参照は認知されません。
認知されないというよりそもそも構文的に存在できません。
(但し、属性値に使えないという意味ではないことに注意が必要です。例えば、 <foo entity="entity-name"/>
(entity 属性は ENTITY
型。)
は正しいです。属性値表記が展開された属性値が
entity-name となります。)
これらの場合には致死的誤りとなります。
[10] 例:
<!DOCTYPE foo [ <!ENTITY % ext SYSTEM "path/to/ext.dtd"> %ext; <!-- これは問題ない。 --> <!ENTITY dtd "<!ELEMENT foo ANY>"> &dtd; <!-- error! --> ]> <foo> <bar title="attribute &val;"/><!-- error! --> </foo> (ext.dtd) <!ENTITY val "value"> <!NOTATION png SYSTEM "path/to/def/of/png"> <!ENTITY % png-image SYSTEM "path/to/png" NDATA png> %png-image; <!-- error! -->
[26] 外部非解析実体への参照が実体値表記内にある場合、 SE までの仕様ではこれを禁止として致命的誤りにしていましたが、 2003-06-04 の修正 <http://www.w3.org/XML/xml-V10-2e-errata#E55> でこれを改め、致命的でない誤りとしました。
これは、既存の実装の中に、そのような場合に致命的誤りとはせずに処理しないだけのものがあったため、 それに譲歩したようです。
[27] 従って、
<!ENTITY image-1 SYSTEM "image1.png" NDATA png> <!ENTITY foo "IMAGE 1: &image-1;">
の扱いは処理系定義となります。
[28] そもそも >>17 で一般実体参照は処理しないのに、 非解析実体の参照の場合だけ別扱いになっていたので、 この修正は妥当なものといえましょう。
[11] 値の型が ENTITY
又は ENTITIES
である属性が指定されていた場合には、
妥当性を検証する処理系は応用にその外部解析実体のシステム/公開識別子及び関連付けられている記法のシステム/公開識別子を通知しなければいけません。
(妥当性を検証しない処理系では期待できません。)
[16] 内部解析実体では実体宣言の実体値の値を、 また外部解析実体ではその実体に含まれている実際の文を、 表記実体値といいます。
内部解析実体の表記実体値の文字参照とパラメーター実体参照を置換したものを、 [置換文といいます。
外部解析実体の置換文は、表記実体値から文宣言を除いたものです。 文字参照やパラメーター実体参照の置換は行われません。
[26] (表記)実体値では文字データとパラメーター実体参照と一般実体参照, それに数値文字参照が使えます。 置換文はこのうちの一般実体参照以外の参照する実体を取込んだ (置換した) ものです。但し、パラメーター実体参照はその置換文が取込まれるのではなく、参照されているパラメーター実体の表記実体値が取り込まれます。
[27] この部分は SE errata で修正されています。 <http://www.w3.org/XML/xml-V10-2e-errata#E7>
[28] >>25 で外部解析実体について参照の置換を行わないとしているのは、 外部解析実体が DTD にも文書本体にも使われ得るからでしょう。
[29] >>28 と >>9 とかの相互作用には注意した方がいいでしょう。
<foo attr="&attr"/> で、
<!ENTITY attr "foo	bar">
の時正規化した属性値は fooSP
bar
になりますが、
<!ENTITY attr SYSTEM "data:,foo%09bar">
なら正規化した属性値は fooTAB
bar
になるでしょう。