実体参照//解決

実体参照//解決

[1] XML実体参照をどう扱うかについて。 (仕様書の <http://www.w3.org/TR/REC-xml#entproc> の辺り。)

[2]

種類パラ内解外解外非文字
内容中の参照認知されない取込む妥当性を検証するなら取込む禁止取込む
属性値中の参照認知されない表記中に取込む禁止取込む
属性値として出現認知されない禁止通知認知されない
実体値中の参照表記中に取込む処理しない誤り取込む
DTD 中の参照PE として取込む禁止禁止

パラ
パラメーター実体 (内部又は外部の解析実体。)
内解
内部一般解析実体
外解
外部一般解析実体
外非
外部非解析実体 (一般実体。)
内容中の参照
要素開始タグ終了タグの間の参照。
属性値中の参照
開始タグ中の属性値指定又は属性並び宣言中の既定値宣言の中の参照。
属性値として出現
型が ENTITY 又は ENTITIESである属性値。 (実体参照ではない。名前そのもの。)
実体値中の参照
実体宣言の値指定中の参照。
DTD 中の参照
DTD 中の適切な場所での参照。但し、「属性値中の参照」, 「実体値中の参照」に該当するものを除く。また、 IGNORE 区間内の参照 (に見えるもの) は解釈されない。

取り込む included

[4] ある実体置換文が取り出されて処理され、 参照のある場所にそれがそもそも存在していたようにされる時、 これを実体を取り込むといいます。 置換文は文字データやマークなどを含むことが出来て、 普通の方法で処理されます。 文字参照はその参照の場所で指示された文字が処理される時取り込まれます。

例えば、 <!ENTITY ATandT "AT&amp;T"> ... <p>昔々あるところに、&ATandT; という&#x28;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」を参照するたびに
     書き換わるのではない。 -->

PE として取り込む

[13] DTD 中のパラメーター実体 (実体値中を除く。) は、妥当性を検証するなら取込みます。 この時、置換文の最初と最後に SP が付加されます。

[14] 例えば、

<!ENTITY % name "ELEMENT">
<!ELEMENT%name;ANY>

は意図したように (<!ELEMENT ELEMENT ANY> として) 解釈されます。

処理しない bypassed

[12] 実体値中の内部解析一般実体への参照は、 処理されずにそのまま素通りします。 実際にその参照を含む実体が参照された時に参照された場所で解決されます。

<!ENTITY a "A">
<!ENTITY ka "K&a;">
...
<foo>&ka;</foo>

foo 要素の内容は ka で、参照を解いて Ka, まだ参照があるので解いて KA, 参照がなくなったのでこれが最終的な内容になります。

<!ENTITY % inner "- an &amp; entity --">
<!ENTITY outer "AN %inner; ENTITY">
...
<foo>AN &outer; ELEMENT</foo>

この例で foo の内容は意図したとおり AN AN - an & entity -- ENTITY ELEMENT になります。 うっかり気を遣って <!ENTITY % inner "- an &amp;amp; entity --"> としてしまうと、本当に AN AN - an &amp; 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&#x2D;name"/> (entity 属性は ENTITY 型。)正しいです。属性値表記が展開された属性値が entity-name となります。)

禁止

[8]

これらの場合には致死的誤りとなります。

[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&#x09;bar"> の時正規化した属性値は fooSPbar になりますが、 <!ENTITY attr SYSTEM "data:,foo%09bar"> なら正規化した属性値は fooTABbar になるでしょう。

メモ