例 5.2
(element foo (make simple-page-sequence ... right-footer: (make external-graphic entity-system-id: "logo.eps" notation-system-id: "EPS")))
先程説明した記法宣言と外部実体宣言を用い、文書中で画像ファイルを参照している場合は、いくつかの問い合わせ式を組み合わせて値を取得し、これを entity-system-id: や notation-system-id: に指定します。ここでは、リスト 5.1、およびリスト 5.2 を用いた例を説明します。
リスト 5.1 [ webstats.dtd ]
<!ELEMENT webstats (year,month,hostname)> <!ELEMENT year (#PCDATA)> <!ELEMENT month (#PCDATA)> <!ELEMENT hostname (#PCDATA)> <!ELEMENT graph EMPTY> <!ATTLIST graph src CDATA #REQUIRED name CDATA #IMPLIED>
リスト 5.2 [ webstats.xml ]
<!xml version="1.0"> <!DOCTYPE webstats SYSTEM "webstats.dtd" [ <!NOTATION jpg SYSTEM "JPEG"> <!ENTITY fig01-01 SYSTEM "visitor-graph-2003-01.jpg" NDATA jpg> <webstats> <year>2003</year> <month>01</month> <hostname>www.nextsolution.co.jp</hostname> <graph src="fig01-01" name="Visitors"/> </webstats>
この文書では、graph タグが画像を参照する要素のひとつになっており、その src 属性には参照する外部実体宣言の名前を記述することになっています。つまり、外部実体宣言のシステム識別子を取得するには、graph タグの src 属性を取得し、src 属性の値から外部実体宣言を参照して、そのシステム識別子を取得するという手順になります。この式をリスト 5.3に示します。
リスト 5.3 [ webstats.dsl ]
(element graph (let* ((node (current-node)) (entity-name (attribute-string "src" node)) (file-name (entity-system-id entity-name node)) (notation-name (if file-name (entity-notation entity-name node) #f)) (file-type (if notation-name (notation-system-id notation-name node) #f))) (if file-type (make external-graphic ... ; その他の特質 entity-system-id: file-name notation-system-id: file-type) (make paragraph (literal "*** ") (if file-name (literal entity-name "の記法宣言が不正です") (literal entity-name "の実体宣言がありません")) (literal " ***")))))
これまでとは異なり、若干プログラミング的な要素が必要になります。順に少しずつ見ていくことにしましょう。
(let* …)
let、let* および、letrec 式は、値を変数に束縛(バインド)する式で、束縛コンストラクタと呼ばれています。厳密には異なりますが、変数に値を代入すると考えておけばよいでしょう。let 式は次の形式で記述します。
(let <束縛部> <本体>) • 束縛部は次の形式をとる ((<変数 1> <初期値 1>) ...)
リスト 5-3 では、((node (current-node)) … (file-type (…))) が束縛
部、(if file-type … (literal ” ***”))) が本体になります。
let 式がすべての初期値を評価してから束縛するのに対し、let*式は初期値の評価
と束縛を一つ一つ逐次的に行います。たとえば、リスト 5.3のように束縛部で前方の
変数を参照する場合は let*式を用います(let 式だとエラーになります)。
(if …)
if は条件式で、構文は次の通りです。
(if <テスト> <帰結部> <代替部>)
if 式は、まず<テスト>を評価し、結果が真であれば帰結部を評価してその結果を返します。<テスト>が偽であった場合は、<代替部>があればそれを評価して結果を返します。代替部がない場合の if 式の結果は未規定です。
リスト 5.3 を例にとると、次の式は変数 file-name が真の値(論理定数 #f 以外は真値とみなされることを思い出してください)であれば (entity-notation …) を評価した結果を返し、そうでなければ論理定数 #f を返します。if 式が返す結果は変数 notation-name に束縛されます。
(notation-name (if file-name (entity-notation entity-name node) #f))
あるいは let* 式の本体にある if 式 (if file-type …) での場合であれば、変数 file-type が真ならば (make external-graphic …) が評価され、偽ならば (make paragraph …) が評価されます。
(current-node)
(current-node) は問い合わせ式のひとつで、現在処理中のノードを返します。
(attribute-string string osnl)
(attribute-string …) は、指定ノードの属性の値を取得する問い合わせ式です。対象となる属性は引数 string に文字列で指定します。引数 osnl(optional singleton node-list)は問い合わせの対象となノードです。この引数は省略可能で、省略時は (current-node) になります。リスト 5.3を例にとると、(current-node) が <graph src=”fig01-01″ …/>を指しているならば、次の式は文字列”fig01-01″を返します。
(attribute-string "src")
(entity-system-id string snl)
外部実体宣言のシステム識別子を取得する問い合わせ式です。string は実体宣言の名前、snl(singleton node-list)は対象の問い合わせとなるノードです。string に一致する実体宣言がない場合、この式は論理定数 #f を返します。実体宣言 fig01-01 のシステム識別子を得るには次のように記述します。この式は、文字列”visitor-graph-2003-01.jpg”を返します。
(entity-system-id string snl)
外部実体宣言のシステム識別子を取得する問い合わせ式です。string は実体宣言の名前、snl(singleton node-list)は対象の問い合わせとなるノードです。string に一致する実体宣言がない場合、この式は論理定数 #f を返します。
実体宣言 fig01-01 のシステム識別子を得るには次のように記述します。この式は、文字列 “visitor-graph-2003-01.jpg” を返します。
(entity-system-id "fig01-01" (current-node))
(entity-notation string snl)
外部実体宣言の記法の名前(NDATA に続く文字列)を返す問い合わせ式です。string は実体宣言の名前です。これは、(entity-system-id …) に指定する引数と同じものになります。リスト 5-2/5-3 では、以下の式は文字列 “jpg” を返します。string に一致する実体宣言がないか、実体宣言に記法の参照がない場合は #f を返します。
(entity-notation "fig01-01" (current-node))
(notation-system-id string snl)
記法宣言のシステム識別子を返す問い合わせ式です。string は記法の名前です。string に一致する記法宣言がなければ #f を返します。リスト 5.2/ 5.3では、以下の式は文字列“JPEG”を返します。
(notation-system-id "jpg" (current-node))
リスト 5-3 では、実体宣言または記法宣言のどちらかのシステム識別子の取得に失敗した場合、画像を配置する代わりに、文書中にエラーメッセージを表示します。