@IT」にはない内容をエンジニアライフで技術紹介するコラム。広く議論する場になることを目指します。2018/02/05前3回に引き続いてEntityDeclについて議論します。今回は、前回の仕様検討に残された議論の余地と構文解析器が置換テキストを構築する処理と定義済み実体の扱いについて読んでいきます。今回、議論の余地があると思われる場所は、4.4.9によって必要になった以下の処理です。整形式性制約の"宣言した実体"妥当性制約の"宣言した実体"の両方に一般実体が入っていないことに起因します。実体宣言AのEntityValueの中にその実体宣言より後ろに実体宣言のある実体Bの参照を書くことができる利点がある一方で単純に参照を認識した時点でエラーにしようとしてもパターン漏れがあるので処理を工夫しなければならないという欠点があります。したときこれをエラーとすることが、現在の処理ではできません。話をややこしくするのが、Content内に実体Aの参照があればその展開処理の中で実体Bの参照を展開しようとして、致命的エラーを検出できるところです。このことが逆説的に、実体Aの参照がContent内に現れなければエラーとして検出できないことも示しています。チェックする方法はいくつかありますが、簡単に思いついたのは次の3つです。案1のデメリットは、一度構文解析したものをもう一度構文解析する無駄が生じる点です。案2は、再構文解析するデメリットはなくなりますが、せっかくチェックしているのに2-2の場合が漏れてしまい、DTD読み込み後に漏れた分をチェックし直す点に、チェック処理の設計として分散するデメリットがあります。結局、案1と案2のデメリットが無い案3を採用するのが良いということが判ります。次に、前回までの説明で実体参照を実体値に入れ替える時と場合について説明してきました。W3Cの勧告では、次に「実体テーブルの値の構築処理」の説明がありますので確認します。実体値の2つの形態を区別すると便利である。内部実体についてリテラル実体値は実体宣言中に実際に存在する引用符で囲われた文字列とする。リテラル実体値は(内部実体の)非終端EntityValueに対応したものとする。外部実体について、リテラル実体値は実体が含んだテキストそのものとする。内部実体について、置換テキストは文字参照とパラメータ実体参照を置換した後のその実体の内容である。外部実体について、置換テキストはテキスト宣言を取り去った後の実体の内容である。(両端のホワイトスペースはそのまま残す。)もし文字参照やパラメータ実体参照が置換テキスト中にあってもそのままにする。それらの参照は、リテラル実体値の中に完全に含まれる必要がある。インクルードした、(もしくはリテラルの中でインクルードした)実際の置換テキストは、上記で説明したように、すべてのパラメータ実体の参照した置換テキストを含む。リテラル実体値中の文字参照に参照した文字を含む。一般実体参照は展開されないままにしておかなければならない。次のような宣言があるとする。"&book;"の参照が文書の内容または属性値として現れた場合となる。----日本語訳----■仕様整理-リテラル実体値EntityValueで示す文字列の両端の引用符を外したものをリテラル実体値と呼びます。一般実体テーブルまたはパラメータ実体テーブルのKeyに対応する値は置換テキストと呼びます。外部実体の置換テキストは、外部識別子が指定した物理構造が含む文字列からテキスト宣言を取り除いた後の値となります。前回少しだけ登場した定義済み実体について説明します。実体参照と文字参照を始め山括弧(小なり)やアンパサンド、またその他の区切り子をエスケープするために使うことができる。quot)はこの目的のために定められたものである。数値文字参照を使うこともできる。数値文字参照は認識されたときに直ちに展開し、文字データとして扱わなければならない。文字参照は、<と&を文字データとして扱いたいときにエスケープするために使われる。]すべてのXMLプロセッサは、これらが宣言してるかいないかに関わらず、その実体を認識しなければならない。相互運用性のために、妥当なXML文書はこれらの実体を他の実体と同じように、その参照を使う前に、宣言すべきである。それらへの参照が整形式の結果を得るために二重のエスケープが必要となる。gtやaposやquotの実体を宣言した場合、置換テキストはエスケープされた1つの文字として宣言しなければならない。(もしくは、その文字への文字参照として宣言しなければならない。二重エスケープは任意であるが、無害である。quotを用意します。quotの実体宣言がなくても宣言した実体として使える必要があります。quotの実体宣言を相互運用性のために定義しても構いません。実体テーブル上の置換テキストは次のようになります。quotに二重エスケープがあったとした場合は次のようになっていても構いません。"---------------実体値テーブル---------------とすればわかるように、置換テキストの値が上記でなければエラーにします。実体宣言で述べたように、実体宣言で同じ名前の実体名を複数回宣言した場合は最初の実体宣言が有効になります。オプションで指定した場合は、2回目以降は重複宣言の警告を出しても良いとあります。これらの仕様は定義済み実体を実装するうえで影響があります。あるように、ユーザのオプションで同名の実体が重複宣言になった場合、警告を出しても良いとあります。置換テキスト)1-4.実体データが有る場合(既に登録してある場合)1-4-1.オプションが有効の場合1-4-1-1.警告を出す1-4-2.オプションが無効の場合1-4-2-1.何もしないとなります。quotの実体宣言を行った場合、1回目の宣言であっても警告を出してしまうという問題があります。DTD読み取り後に定義済み実体を登録する一般実体の参照を処理するタイミングはDTDの作成後ですから、DTDをすべて処理したあとに定義済み実体を該当keyがない場合だけ登録するインタフェースを用意する方法です。初期化時に定義済み実体を登録するが、上書きする場合は初回だけにする定義済み実体という名前に合わせて、テーブルのコンストラクタと同時に登録する方法です。3種類の実体があり、定義済み実体と同じkeyで外部実体や解析対象外実体も登録できてしまいます。データにマージする(定義済み実体でないマージ処理へ)以下の処理では、定義済み実体を個別に処理する部分を削除します。整形式性制約エラー2-3-1-3.再帰用のスタックに既に同名の実体名が無い場合2-3-1-3-1.再帰用のスタックに実体名を追加する2-3-1-3-2.置換テキストRepTextを取得する2-3-1-3-3.一般実体のトークン列の代わりにCharData(RepText)を返す。整形式性制約エラー2-3-1-3.再帰用のスタックに既に同名の実体名が無い場合2-3-1-3-1.再帰用のスタックに実体名を追加する2-3-1-3-2.置換テキストRepTextを取得する2-3-1-3-3.一般実体のトークン列の代わりにNORMAL_TOKEN_A1(RepText)または、NORMAL_TOKEN_A2(RepText)を返す。整形式性制約エラー2-3-1-3.再帰用のスタックに既に同名の実体名が無い場合2-3-1-3-1.再帰用のスタックに実体名を追加する2-3-1-3-2.置換テキストRepTextを取得する2-3-1-3-3.一般実体のトークン列の代わりにNORMAL_TOKEN_A1(RepText)または、NORMAL_TOKEN_A2(RepText)を返す。通信系と自動車関連のシステム開発の下請けを経て、現在は家業を継いでIT系の仕事から離れています。本コラムは趣味で研究している内容がメインです。あなたはどこ見ていますか?書籍「誰でも身につく!暗算力」を読んでみた。未成年者略取ムチャか?男気か?部下も立て続けに。利用規約ITmediaはアイティメディア株式会社の登録商標です。