本家「@IT」にはない内容をエンジニアライフで技術紹介するコラム。広く議論する場になることを目指します。

第051回_EntityDecl_物理構造

»
今回はEntityDeclの物理構造について議論します。

今回からDTDの中身について検討・実装していきます。
最初に検討するDTDはEntityDeclです。
※このコラムは不人気なため、他のDTDはコラム上では検討しません。無念です。

EntityDeclはW3Cの勧告において「4 物理構造」の章すべてを使って
説明しているボリュームの大きい内容です。

本コラムでも1回ではとても検討しきれませんので複数回に分けて説明します。

EntityDeclのW3Cの勧告内容

----W3C勧告----
4 Physical Structures

[Definition: An XML document may consist of one or many storage units. These are called entities;
they all have content and are all (except for the document entity and the external DTD subset)
identified by entity name.] Each XML document has one entity called the document entity,
which serves as the starting point for the XML processor and may contain the whole document.

Entities may be either parsed or unparsed. [Definition: The contents of a parsed entity are referred to as its
replacement text; this text is considered an integral part of the document.]

[Definition: An unparsed entity is a resource whose contents may or may not be text, and if text, may be other
than XML. Each unparsed entity has an associated notation, identified by name. Beyond a requirement that
an XML processor make the identifiers for the entity and notation available to the application,
XML places no constraints on the contents of unparsed entities.]

Parsed entities are invoked by name using entity references; unparsed entities by name, given in the value of
ENTITY or ENTITIES attributes.

[Definition: General entities are entities for use within the document content. In this specification, general
entities are sometimes referred to with the unqualified term entity when this leads to no ambiguity.] [Definition:
Parameter entities are parsed entities for use within the DTD.] These two types of entities use different forms of
reference and are recognized in different contexts. Furthermore, they occupy different namespaces; a parameter
entity and a general entity with the same name are two distinct entities.
----W3C勧告----
----日本語訳----
4 物理構造
[定義: XML文書は1つまたは複数の記録単位によって構成する。
   これらの記録単位を実体と呼ぶ。;
   全ての実体は内容を持つ。
   文書実体と外部DTDサブセットを除く実体は、
   実体名を持つ。(実体名で識別できる。)]

各XML文書は文書実体と呼ばれる1つの実体を持つ。
文書実体は、XMLプロセッサの開始点になり、文書すべてを含むこともある。

実体は解析対象となることもあるし、ならないこともある。
[定義: 解析対象実体の内容のことを置換テキストと呼ぶ。;
   この置換テキストは文書の必要不可欠な部分と考えられる。]

[定義: 解析対象外実体は、その内容がテキストになる場合もあるし、
    テキストにならない場合もあるというリソースである。
    テキストの場合、XMLでないこともある。
    それぞれの解析対象外実体は関連付けられた記法を持つ。
    記法は記法名によって識別する。
    XMLプロセッサがアプリケーションにとって入手可能な実体と
    記法の識別子を与えることだけを要件とする。
    XMLは解析対象外実体の内容に対して制約するものはない。]

解析対象実体は、実体参照をつかって参照名を元に呼び出す。;
解析対象外実体も参照名を元に呼び出すが、ENTITY属性かENTITIES属性の値としてのみ与えることができる。

[定義: 一般実体は文書の内容の中に現れる実体である。
    この仕様書において、他の種類の実体との曖昧さを
    引き起こさない場合は、単に実体と呼ぶ場合もある。]
[定義: パラメータ実体は、DTDの中に現れる解析実体である。]
これら2つの型の実体は、参照方法も異なり、異なるコンテキストで認識する。
さらに、異なる名前空間に存在する。; つまり、同じ名前を持ったパラメータ実体と一般実体は、2つの区別された実体とする。
----日本語訳----

EntityDeclの仕様整理

物理構造についてのおさらいと分析
コラム第39回で説明したように、XML文書は物理構造と論理構造の概念に分けて考えることができます。といっても、どちらの概念に属するから実装はこうなるということはありません。章別け程度のものです。

XML文書はN個の実体によって構成すると書いてありますが、このコラム風に言えばXML文書はデータ構造として木構造(抽象構文木)を形成します。ですから、木構造(抽象構文木)を文書実体と呼ぶことができます。

XMLの概念が基本となる記憶単位をEntity(実体)と定義するのに対してクラスで管理するデータ構造の単位をEntityとするのは非効率です。実体の用途は種類毎に異なるため、データ構造は木構造であったり、テーブルのレコードであったりと用途に合わせたものを選ぶ方が利便性を高めることができます。

実体の構成
実体は基本的に、実体名と内容からなります。
ただし、文書実体と外部サブセットは名前を持ちません。

内容が解析対象の場合は、特別に置換テキストと呼びます。
内容が解析対象外の場合は、特別な呼び名はありません。

実体名は名前空間を持ちます。異なる名前空間というのは実装上は管理するテーブルの種類が異なることを意味します。
一般実体とパラメータ実体は異なる名前空間を持ちますから、
 GeneralEntityMap<Key,ReplacementText>

 ParameterEntityMap<Key,ReplacementText>
を別々に管理すれば良いということです。
それぞれは参照名(Key)を持ちますが、同じ参照名(Key)を持っていてもそれぞれのMapは正しく管理できます。

実体の種類の理解の仕方について
このパラグラフに実体の種類についての記載がありますが、これはわざとわかり難くしているのでは?と思えてきます。
生成規則と照らし合わせながら考えることで簡単に理解できると思います。

関連する構文は
 EntityDecl::= GEDecl | PEDecl
 GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
 PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
 EntityDef ::= EntityValue | (ExternalID NDataDecl?)
 PEDef ::= EntityValue | ExternalID
となります。

実体の種類: 実体宣言できない実体と宣言できる実体
実体宣言できない実体は、文書実体と外部サブセットです。
実体宣言できる実体は、
 EntityDecl::= GEDecl | PEDecl
ですので、
 GE(General Entity、邦訳:一般実体)

 PE(Parameter Entity、邦訳:パラメータ実体)
が宣言できます。

実体宣言で宣言できる実体の種類:一般実体とパラメータ実体
一般実体(General Entity)は、GEDeclの構文で宣言する実体です。
一般実体には、解析対象と解析対象外の実体があり、それぞれ記載位置が異なりますのであとで説明します。

パラメータ実体(Parameter Entity)は、PEDeclの構文で宣言する解析対象実体です。
パラメータ実体の置換テキストはマークアップ宣言の一部になります。
記載できる場所は、--マークアップ宣言の回に説明した部分もありますが--、
 intマークアップ宣言の宣言の間(DeclSep)、
 およびintマークアップ宣言の実体宣言の内容(EntityValue)
 DeclSepマークアップ宣言の宣言の間(DeclSep)、
 DeclSepマークアップ宣言の実体宣言の内容(EntityValue)
 およびextマークアップ宣言の各マークアップ宣言の先頭と末尾を含まない位置
 extマークアップ宣言の宣言の間(DeclSep)、
 extマークアップ宣言の実体宣言の内容(EntityValue)
 およびextマークアップ宣言の各マークアップ宣言の先頭と末尾を含まない位置
にパラメータ実体の参照(PEReference)を記載できます。

※補足
内容(EntityValue)は一般実体の構文と共有の構文のため、その結果がマークアップ宣言の一部にならない場合もあり得ます。
ただし、その場合は後述する「置換テキストの展開処理」でエラーになるので、
パラメータ実体の内容はマークアップ宣言の一部になると言えます。

一般実体の種類:(内部/外部)解析対象実体と解析対象外実体
一般実体の構文
 GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
 EntityDef ::= EntityValue | (ExternalID NDataDecl?)
を結合し、パターン分けすると
 InternalParsedGEDecl ::= '<!ENTITY' S Name S EntityValue S? '>'
 ExternalParsedGEDecl ::= '<!ENTITY' S Name S ExternalID S? '>'
 UnParsedGEDecl ::= '<!ENTITY' S Name S ExternalID NDataDecl S? '>'
の3つに分かれます。非終端につけた名前から判る通り、
 EntityDefがEntityValueだけの場合、 一般実体-内部-解析対象実体
 EntityDefがExternalIDだけの場合、 一般実体-外部-解析対象実体
 ENtityDefがExternalID NDataDeclの場合、一般実体-外部-解析対象外実体
と呼びます。

#これらの生成規則は説明の判り易さのために作成しましたが、実装では使いません。

一般実体-内部/外部-解析対象実体は、内容(置換テキスト)をXMLの構文の一部として解析する実体です。
EntityValueないしExternalIDが示すURIに置換テキストを持ち、置換テキストは文書実体の一部になります。
解析対象実体の記載位置は、
 contentの中
 EntityValueの中(ただし自己参照/循環参照してはいけない)
 属性のデフォルト値を示す(AttValue)の中
に記載できます。

#
# 補足
# 内容(EntityValue)はパラメータ実体の構文と共有の構文のため、
# その結果が文書実体の一部にならない場合もあり得ます。
# ただし、その場合は後述する「置換テキストの展開処理」でエラーになるので、
# 一般実体の内容(置換テキスト)は文書実体の一部になると言えます。
#

一方、解析対象外実体は内容をXMLの構文の一部とせず、XMLプロセッサを呼び出したアプリケーションへ、その内容を通知する実体です。例えばXML文書に画像ファイルを添付したい場合は、内容をXMLの構文で解析できませんから、解析対象外の実体としてアプリケーションに通知します。

解析対象実体の通知方法
XMLプロセッサは、実体参照があると、実体参照が示す参照名をkeyに一般実体テーブルまたはパラメータ実体テーブルを検索し、実体参照を置換テキストに置き換えます。

#
# 実体参照や置換テキストへの置き換え手順については次回以降に説明します。
#

解析対象外実体の通知方法
XMLプロセッサは、contentの属性値(AttValue)が属性型:ENTITY属性またはENTITIES属性の場合、その属性名をkeyに一般実体テーブルで検索し、属性名に対して解析対象外実体とのリンクを作ります。

#
# 作成したリンクを元に上位アプリケーションへ解析対象外実体を通知します。
#

パラメータ実体の種類:(内部/外部)解析対象実体
一般実体の構文
 PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
 PEDef ::= EntityValue | ExternalID
を結合し、パターン分けすると
 InternalParsedPEDecl ::= '<!ENTITY' S '%' S Name S EntityValue S? '>'
 ExternalParsedPEDecl ::= '<!ENTITY' S '%' S Name S ExternalID S? '>'
の2つに分かれます。非終端につけた名前から判る通り、
 PEDefがEntityValueだけの場合、 パラメータ実体-内部-解析対象実体
 EntityDefがExternalIDだけの場合、 パラメータ実体-外部-解析対象実体
と呼びます。
Comment(0)

コメント

コメントを投稿する