文書型定義( DTD ) は、 SGMLファミリマークアップ言語( GML、SGML、XML、HTML )の文書型を定義する一連のマークアップ宣言を含む仕様ファイルです。 DTD 仕様ファイルは、文書の検証に使用できます。
DTDはXML文書の有効な構成要素を定義します。検証された要素と属性のリストで文書構造を定義します。DTDはXML文書内でインライン宣言することも、外部参照として宣言することもできます。[1]
DTD の名前空間対応バージョンは、 ISO DSDLのパート 9 として開発されています。DTD は、 ISO SGML 標準作業の一部として定義されたより大きなセットから派生したXML および HTML 文字実体参照などの特別な公開文字を必要とするアプリケーションで使用されます。XMLはSGML DTD のサブセットを使用します。
2009 年現在、 XML 構造を検証するためのより優れた方法として、 [アップデート]新しいXML 名前空間対応スキーマ言語( W3C XML スキーマやISO RELAX NGなど) が DTD に取って代わりました。
DTD をドキュメントに関連付ける
DTDは、文書型宣言(DOCTYPE)によってXMLまたはSGML文書に関連付けられます。DOCTYPEは、XML文書の先頭近くの構文フラグメントdoctypedeclに出現します。 [2]この宣言により、文書が参照先のDTDによって定義された型のインスタンスであることが確立されます。
DOCTYPE は 2 種類の宣言を行います。
- オプションの外部サブセット
- オプションの内部サブセット。
内部サブセットの宣言は、文書自体の DOCTYPE の一部を形成します。外部サブセットの宣言は、別のテキスト ファイルにあります。外部サブセットは、パブリック識別子および/またはシステム識別子を介して参照できます。文書を読み取るプログラムは、外部サブセットを読み取る必要がない場合があります。
DTD で外部サブセットを参照する、またはDTD で宣言された解析済みの外部エンティティ(内部サブセット内で宣言されたものを含む) への参照が本文に含まれる有効な SGML または XML ドキュメントは、スタンドアロンモードで検証するSGML または XML パーサーによって部分的にしか解析できず、完全に検証することはできません(つまり、これらの検証パーサーはこれらの外部エンティティを取得しようとせず、その置換テキストにアクセスできません)。
ただし、このようなドキュメントは、検証パーサーの非スタンドアロン モードでは完全に解析可能です。検証パーサーは、指定された公開識別子(FPI)またはシステム識別子(URI) でこれらの外部エンティティを見つけられない場合、またはアクセスできない場合は、エラーを通知します。(DTD で宣言された表記法も外部エンティティを参照していますが、これらの解析されていないエンティティは、これらのパーサーのスタンドアロンモードでのドキュメントの検証には必要ありません。表記法によって参照されるすべての外部エンティティの検証は、SGML または XML パーサーを使用するアプリケーションに任されています)。非検証パーサーは、最終的には、非スタンドアロン モードでこれらの外部エンティティを見つけようとしますが(宣言された解析可能なエンティティを解決するためだけに DTD を部分的に解釈することによって)、これらのドキュメントのコンテンツ モデルは検証しません。
例
次の DOCTYPE の例には、パブリック識別子とシステム識別子の両方が含まれています。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
すべての HTML 4.01 ドキュメントは、3 つの SGML DTD のいずれかに準拠しています。これらの DTD のパブリック識別子は一定であり、次のようになります。
-//W3C//DTD HTML 4.01//EN-//W3C//DTD HTML 4.01 Transitional//EN-//W3C//DTD HTML 4.01 Frameset//EN
これらの DTD のシステム識別子は、DOCTYPE 内に存在する場合、URI 参照です。システム識別子は通常、解決可能な場所にある特定の宣言セットを指します。SGML では、ドキュメント解析ソフトウェアが使用する URI リゾルバーでオプションとして使用できるカタログ内のシステム識別子にパブリック識別子をマッピングできます。
この DOCTYPE は、ドキュメント構文が XML に準拠している場合、オプションのXML 宣言の後、ドキュメント本体の前にのみ出現できます。これには、XHTMLドキュメントが含まれます。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- XHTML 文書本体はここから始まります-->
<html xmlns= "http://www.w3.org/1999/xhtml" > ...
</html>
外部サブセットの後に、追加の内部サブセットを提供することもできます。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [
<!-- ここに内部サブセットを埋め込むことができます -->
]>
<!-- XHTML ドキュメント本体はここから始まります-->
<html xmlns= "http://www.w3.org/1999/xhtml" > ...
</html>
あるいは、内部サブセットのみを提供することもできます。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html [
<!-- 内部サブセットをここに埋め込むことができます -->
]>
<!-- XHTML ドキュメント本体はここから始まります-->
<html xmlns= "http://www.w3.org/1999/xhtml" > ...
</html>
最後に、ドキュメント タイプ定義にはサブセットがまったく含まれない場合があります。その場合、ドキュメントに単一のトップレベル要素があることを指定するだけです (これはすべての有効な XML および HTML ドキュメントに対する暗黙の要件ですが、トップレベル要素が暗黙のルート要素と異なる可能性があるドキュメント フラグメントやすべての SGML ドキュメントには適用されません)。また、ルート要素のタイプ名を示します。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<!-- XHTML ドキュメント本体はここから始まります-->
<html xmlns= "http://www.w3.org/1999/xhtml" > ...
</html>
マークアップ宣言
DTD は、要素宣言と属性リスト宣言によってドキュメントのクラスの構造を記述します。要素宣言は、ドキュメント内の許容される要素セットを指定し、宣言された要素と文字データの連続が各要素内に含まれるかどうか、およびその方法を指定します。属性リスト宣言は、宣言された各要素の許容される属性セットを指定します。これには、明示的な有効値セットでない場合は、各属性値のタイプ も含まれます。
DTDマークアップ宣言は、対応するXML文書のクラスの構造でどの要素タイプ、属性リスト、エンティティ、表記法が許可されるかを宣言します。[3]
要素型宣言
要素タイプ宣言は、要素とその可能なコンテンツを定義します。有効な XML ドキュメントには、DTD で定義されている要素のみが含まれます。
さまざまなキーワードと文字が要素の内容を指定します。
EMPTY定義された要素にコンテンツが許可されないことを指定します。つまり、子要素、さらにはテキスト要素も持つことができません (空白がある場合は無視されます)。ANY定義された要素が制限なく任意のコンテンツを許可することを指定します。つまり、任意の数(0 を含む)および種類の子要素(テキスト要素を含む)を持つことができます。- または、定義された要素のコンテンツ内で直接の子として許可される要素のみを指定する式。このコンテンツは次のいずれかになります。
- 混合コンテンツ。つまり、コンテンツには少なくとも 1 つのテキスト要素と 0 個以上の名前付き要素を含めることができますが、それらの順序と出現回数は制限できません。これは次のようになります。
( #PCDATA ): 歴史的には解析された文字データを意味し、コンテンツには 1 つのテキスト要素のみが許可されます (量指定子は許可されません)。( #PCDATA | ''element name'' | ... )*: 2 つ以上の子要素 (テキスト要素または指定された名前付き要素のみを含む) の限定された選択肢 (括弧で囲まれた排他的リストで、|パイプ文字 " " で区切られ、必要な "*" 量指定子で終了) は、コンテンツ内で任意の順序と出現回数で使用できます。
- 要素コンテンツ。これは、コンテンツの子要素にテキスト要素があってはならないことを意味します (子要素間にある空白はすべて、コメントと同様に無視されます)。このような要素コンテンツは、終端記号のないバッカスナウア記法の変形でコンテンツ パーティクルとして指定され、要素名は非終端記号として指定されます。要素コンテンツは次の要素で構成されます。
- コンテンツパーティクルは、 DTD で宣言された要素の名前、シーケンス リスト、または選択リストのいずれかになります。オプションで量指定子が続く場合もあります。
- シーケンスリスト
,とは、 1 つ以上のコンテンツ パーティクルの順序付きリスト (括弧で囲み、" " カンマ文字で区切る) を意味します。すべてのコンテンツ パーティクルは、定義された要素のコンテンツ内の直接の子として、指定された位置と相対順序で連続して出現する必要があります。 - 選択リストとは
|、2 つ以上のコンテンツ パーティクルの相互に排他的なリスト (括弧で囲み、パイプ文字 " " で区切る) を意味します。定義された要素のコンテンツ内の同じ位置には、これらのコンテンツ パーティクルのうち 1 つだけが表示される場合があります。
- シーケンスリスト
- 量指定子は、要素のコンテンツ内の指定された位置でこれらの項目が連続して出現する回数を制限するために、適用される指定された項目の直後に続く単一の文字です。量指定子は次のいずれかになります。
+項目が 1 回以上出現する必要があることを指定します。出現ごとに有効な内容が異なる場合があります。*任意の数(0 個以上)の出現が許可されることを指定します。項目はオプションであり、出現ごとに有効な内容が異なる場合があります。?複数回出現してはならないことを指定します。この項目はオプションです。- 量指定子がない場合、指定された項目は要素のコンテンツ内の指定された位置に 1 回だけ出現する必要があります。
- コンテンツパーティクルは、 DTD で宣言された要素の名前、シーケンス リスト、または選択リストのいずれかになります。オプションで量指定子が続く場合もあります。
- 混合コンテンツ。つまり、コンテンツには少なくとも 1 つのテキスト要素と 0 個以上の名前付き要素を含めることができますが、それらの順序と出現回数は制限できません。これは次のようになります。
例えば:
<!ELEMENT html ( head , body ) >
<!ELEMENT p ( #PCDATA | p | ul | dl | table | h1 | h2 | h3 )* >
要素タイプ宣言は、検証を行わないSGML および XML パーサーでは無視されます(この場合、解析されたドキュメント内で任意の順序および任意の数の要素が受け入れられます)。ただし、これらの宣言の形式と有効性は引き続きチェックされます。
属性リストの宣言
属性リストは、特定の要素タイプに対して、そのタイプに関連付けられているすべての可能な属性のリストを指定します。可能な属性ごとに、次のものが含まれます。
- 属性の宣言名、
- データ型(または可能な値の列挙)
- およびそのデフォルト値。[4]
例えば:
<!ATTLIST img
src CDATA #REQUIRED
id ID #IMPLIED
sort CDATA #FIXED "true"
print ( yes | no ) "yes"
>
SGML と XML の両方でサポートされている属性タイプをいくつか示します。
CDATA- このタイプは文字データを意味し、属性が固定として指定されていない限り、属性の有効値は任意のテキスト値になる可能性があることを示します (DTD 内のコメントでは、実際に受け入れられる値をさらに文書化できますが、DTD 構文ではそのような正確な指定は許可されません)。
ID- 属性の有効値は有効な識別子でなければならず、この定義済み識別子を使用した参照のターゲットを定義して現在の要素に固定するために使用されます (URI の末尾の "#" 記号の後に指定できるドキュメントフラグメント識別子を含む)。同じドキュメント内の異なる要素が同じ識別子を定義している場合はエラーになります。一意性制約は、識別子自体に他のセマンティクスがないこと、およびアプリケーションで識別子を不透明として扱う必要があることも意味します。XML では、
xml:idこのタイプの標準疑似属性 " " も事前定義されており、DTD での宣言は必要ありません。そのため、一意性制約は、これらの定義済み識別子が XML ドキュメント内のどこで指定されても適用されます。 IDREFまたはIDREFS- 属性の有効値は有効な識別子(またはスペースで区切られた識別子のリスト)のみであり、
IDDTD でその型で宣言された属性を持つ文書で定義された一意の要素(または擬似属性 " " を持つ XML 文書で定義された一意の要素xml:id)を参照している必要があり、その有効値は同じ識別子である必要があります。 NMTOKENまたはNMTOKENS- 属性の有効な値は、有効な名前トークン(またはスペースで区切られた名前トークンのリスト)のみになりますが、文書内の一意の識別子に限定されません。この名前は、補足的かつアプリケーション依存のセマンティクスを持ち、追加の命名制約を必要とする場合がありますが、これは DTD の範囲外です。
ENTITYまたはENTITIES- 属性の有効な値は、解析されない外部エンティティの名前(またはスペースで区切られた名前のリスト)のみであり、文書型宣言でも宣言する必要があります。この型は HTML パーサーではサポートされていませんが、SGML および XML 1.0 または 1.1(XHTML および SVG を含む)では有効です。
(value1|...)- 属性の有効な値は、テキスト値の列挙リスト(括弧で囲み、
|パイプ文字「 」で区切る)のいずれか 1 つだけになります。列挙内の各値は、単純な名前トークンでない場合は、'一重引用符'または"二重引用符で囲んで指定できます。" NOTATION (notation1|...)- 属性の有効な値は、表記名の列挙リスト(括弧で囲み、
|パイプ文字「 」で区切る)のいずれか 1 つだけになります。列挙内の各表記名は、文書型宣言でも宣言されている必要があります。この型は HTML パーサーではサポートされていませんが、SGML および XML 1.0 または 1.1(XHTML および SVG を含む)では有効です。
デフォルト値は、属性が出現する必要があるか ( #REQUIRED)、出現しないか ( #IMPLIED)、属性が固定値を持つか ( #FIXED)、または指定された属性が XML タグ内で省略されている場合にデフォルト値としてどの値を使用するか ("…") を定義できます。
属性リスト宣言は、検証を行わないSGML および XML パーサーでは無視されます(この場合、解析されたドキュメントのすべての要素内で任意の属性が受け入れられます)。ただし、これらの宣言は、整形式性と妥当性についてはチェックされます。
エンティティ宣言
エンティティはマクロに似ています。エンティティ宣言は、文書全体で保持される値を割り当てます。一般的な用途は、見慣れない文字に対して、数値文字参照よりも認識しやすい名前を付けることです。[5]エンティティは、XMLテキストの読みやすさを向上させるのに役立ちます。一般に、内部と外部の2つのタイプがあります。
- 内部 (解析対象) エンティティは、宣言で定義された任意のテキスト コンテンツ (ドキュメントで宣言された DTD の内部サブセットまたは外部サブセットにある場合があります) に名前を関連付けます。その後、名前付きエンティティ参照がドキュメントの残りの部分 (DTD の残りの部分を含む) で検出され、このエンティティ名が解析対象エンティティとして実際に定義されている場合、参照自体は解析対象エンティティで定義されたテキスト コンテンツに直ちに置き換えられ、この置換テキスト内で解析が続行されます。
- 定義済みの名前付き文字エンティティは内部エンティティに似ていますが、そのうち 5 つはすべての SGML、HTML、および XML パーサーで特別に扱われます。これらのエンティティは通常の解析済みエンティティとは少し異なります。ドキュメント内で名前付き文字エンティティ参照が検出されると、参照もエンティティで定義された文字コンテンツにすぐに置き換えられますが、置換テキストの後に解析が続行され、置換テキストは現在解析中のトークンに文字どおりにすぐに挿入されます (そのような文字がそのトークンのテキスト値で許可されている場合)。これにより、HTML または XML 自体のコア構文に必要な一部の文字を、その特殊な構文上の役割からエスケープできます (特に、エンティティ参照の開始用に予約されている "&"、マークアップ タグを区切る "<" または ">"、属性とエンティティ定義の値を区切る "二重" または "一重" 引用符)。定義済み文字エンティティには、同様に処理される数値文字参照も含まれており、これらを使用して、表す文字をエスケープしたり、ドキュメント エンコーディングでサポートされている文字レパートリーの制限を回避したりすることもできます。
- SGML の基本プロファイルまたは HTML ドキュメントでは、内部エンティティの宣言はできません (外部 DTD サブセットは取得されず、内部 DTD サブセットはこれらの基本プロファイルではサポートされていないため)。
- 代わりに、HTML 標準では、数百の名前付き文字エンティティの大規模なセットが事前定義されており、これらは、パーサーによって使用される DTD で定義された標準の解析対象エンティティとして処理できます。
- 外部エンティティは、外部ストレージ オブジェクトを指します。これらはドキュメント内で一意の名前で宣言され、コンテンツのソースを指定する
パブリック識別子 (FPI) および/またはシステム識別子 ( URIとして解釈される) で定義されます。実際には、次の 2 つのバリエーションが存在します。
- 定義で名前付き注釈に関連付けられていない解析された外部エンティティ(ほとんどの場合、そのコンテンツの URI を示す SYSTEM 識別子で定義されます)。この場合、検証 XML または SGML パーサーは、そのコンテンツを取得し、内部エンティティ(有効な置換テキストを含む外部エンティティ)として宣言されているかのように解析します。
- 注釈名で定義され、関連付けられている解析されない外部エンティティ。この場合、それらは不透明な参照として扱われ、SGML または XML パーサーを使用してアプリケーションにその旨が通知されます。それらの解釈、取得、および解析は、サポートされる注釈の種類に応じて、アプリケーションに委ねられます (注釈と解析されない外部エンティティの例については、次のセクションを参照してください)。
- 外部エンティティは、SGML の基本プロファイルや HTML ドキュメントではサポートされていませんが、SGML の完全な実装や XML 1.0 または 1.1 (これらのドキュメント タイプで厳密に必要ではない場合でも、XHTML や SVG を含む) では有効です。
内部エンティティ宣言の例(ここでは SGML ドキュメントの内部 DTD サブセット内)は次のとおりです。
<!DOCTYPE sgml [
<!ELEMENT sgml ANY >
<!ENTITY % std "standard SGML" >
<!ENTITY % signature " — &author;." >
<!ENTITY % question "なぜ自分の本を %std; で直接出版できないのか?" >
<!ENTITY % author "ウィリアム シェイクスピア" >
]>
<sgml> &question;&signature; </sgml>
内部エンティティは、DTD またはドキュメント本体で参照および解析されない限り、解析順に任意の順序で定義できます。解析されたエンティティのコンテンツ内に、まだ定義されていないエンティティへの参照を含めることは有効ですが、このエンティティが完全に定義される前に、その定義されたコンテンツで参照される他のすべての内部エンティティを含む、名前付きエンティティ参照を他の場所に含めることは無効です (これにより、内部エンティティの循環または再帰的な定義も防止されます)。このドキュメントは、次のように解析されます。
<!DOCTYPE sgml [
<!ELEMENT sgml ANY >
<!ENTITY % std "standard SGML" >
<!ENTITY % signature " — &author;." >
<!ENTITY % question "なぜ私の本を標準SGMLで直接出版できないのか?" >
<!ENTITY % author "ウィリアム・シェイクスピア" >
]>
<sgml>なぜ標準SGMLで直接本を出版 できないのでしょ うか? —ウィリアムシェイクスピア。</sgml>
「author」内部エンティティへの参照は、「signature」内部エンティティの置換テキストでは置換されません。代わりに、「signature」エンティティ参照が「sgml」要素のコンテンツ内で解析されたときにのみ置換されますが、検証パーサーによってのみ置換されます (検証しないパーサーは、要素のコンテンツ内またはドキュメント本体内の属性値内で発生するエンティティ参照を置換しません)。
これが可能なのは、内部エンティティ定義で指定された置換テキストによって、パラメータエンティティ参照 (「%」文字によって導入され、その置換が解析された DTD コンテンツに適用される) と一般エンティティ参照 (「&」文字によって導入され、その置換が効果的に解析および検証されるまで遅延される) を区別できるためです。DTD でパラメータ エンティティ参照を導入するための「%」文字は、DTD の外部では特別な役割を失い、リテラル文字になります。
ただし、定義済みの文字エンティティへの参照は、検証パーサーを必要とせずに、どこで発生しても置換されます (「&」文字によってのみ導入されます)。
表記宣言
表記法は SGML または XML で使用されます。表記法は、解析されない外部エンティティへの完全な参照を提供します。外部エンティティの解釈はアプリケーションに委ねられます (アプリケーションは外部エンティティを直接解釈するか、外部エンティティ自体を取得します)。この参照は、ドキュメント本体で使用できる単純な名前を割り当てることによって行われます。たとえば、表記法は XML 1.1 ドキュメント内の非 XML データを参照するために使用できます。たとえば、SVG イメージに注釈を付けて特定のレンダラーに関連付けるには、次のようにします。
<!NOTATION type-image-svg SYSTEM "image/svg" >
これは、このタイプの外部画像のTEXTを宣言し、それを表記法名 "type-image-svg" に関連付けます。ただし、表記法名は通常、表記法を生成または使用するアプリケーションに固有の命名規則に従います。表記法は、有効なコンテンツが外部エンティティであり、XML または SGML パーサーによって使用されるカタログに登録されている PUBLIC FPI か、解釈がアプリケーションに依存する SYSTEM URI (ここでは相対 URI として解釈される MIME タイプですが、特定のレンダラーへの絶対 URI や、UUID などの OS 固有のオブジェクト識別子を示す URN の場合もあります) である追加のメタデータとして解釈されます。
宣言された表記法名は、少なくともXMLに準拠するためには、すべての文書型宣言内、つまり外部サブセットと内部サブセット内で一意でなければなりません。[6] [7]
SGML または XML ドキュメントの本文に含まれる解析されていない外部エンティティに表記法を関連付けることができます。これらの外部エンティティのPUBLICorSYSTEMパラメータは、外部エンティティの解析されていないデータがある FPI および/または URI を指定し、NDATAこれらの定義済みエンティティの additional パラメータは追加の表記法 (つまり、ここでは実質的に MIME タイプ) を指定します。例:
<!DOCTYPE sgml [
<!ELEMENT sgml ( img )* >
<!ELEMENT img EMPTY >
<!ATTLIST img
data ENTITY #IMPLIED >
<!ENTITY example1SVG SYSTEM "example1.svg" NDATA example1SVG-rdf >
<!NOTATION example1SVG-rdf SYSTEM "example1.svg.rdf" >
]>
<sgml>
<imgデータ = "example1SVG" /> </sgml>
SGML 文書の本文では、参照されるこれらの外部エンティティ (名前は「&」と「;」の間に指定されます) は、通常の名前付きエンティティ (CDATA 値で定義されます) のように置き換えられず、DTD が要素の宣言されたコンテンツ タイプまたは属性の宣言されたタイプ (ここでは属性のタイプ) でこのような外部エンティティを許可するか、SGML パーサーがコンテンツを検証していない限り、要素属性の値 (上記ENTITYのようなdata) として、または要素コンテンツ内で使用できる個別の未解析トークンとして残されます。
表記法は、他の外部エンティティに関連付けることなく、要素に追加のメタデータとして直接関連付けることもできます。その場合は、表記法の名前を、要素の宣言内の DTD で宣言されている追加属性の可能な値として指定します。例:
<!ATTLIST ...>
<!DOCTYPE sgml [
<!ELEMENT sgml ( img )* >
<!--
オプションの "type" 属性値は、この表記法にのみ設定できます。
-->
<!ATTLIST sgml
type NOTATION (
type-vendor-specific ) #IMPLIED >
<!ELEMENT img ANY > <!-- オプションのコンテンツは、解析可能な SGML または XML データのみにすることができます -->
<!--
オプションの "title" 属性値は、テキストとして解析可能でなければなりません。
オプションの "data" 属性値は、解析されない外部エンティティに設定されます。
オプションの "type" 属性値は、2 つの表記法のうちの 1 つにのみすることができます。
-->
<!ATTLIST img
title CDATA #IMPLIED
data ENTITY #IMPLIED
type NOTATION (
type-image-svg |
type-image-gif ) #IMPLIED >
<!--
表記法は外部エンティティを参照しており、上記の「type」属性で設定するか
、解析できない定義済みの外部エンティティによって参照される必要があります。
-->
<!NOTATION type-image-svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!NOTATION type-image-gif PUBLIC "image/gif" >
<!NOTATION type-vendor-specific PUBLIC "application/VND.specific+sgml" >
<!ENTITY example1SVGTitle "example1.svg のタイトル" > <!-- 解析された内部エンティティ -->
<!ENTITY example1SVG SYSTEM "example1.svg" > <!-- 解析された外部エンティティ -->
<!ENTITY example1GIFTitle "example1.gif のタイトル" > <!-- 解析された内部エンティティ -->
<!ENTITY example1GIF SYSTEM "example1.gif" NDATA type-image-gif > <!-- 解析されていない外部エンティティ -->
]>
<sgml type= "type-vendor-specific" > <!-- SVG イメージは有効な SGML または XML テキストとして解析可能です --> <img title= "&example1SVGTitle;" type= "type-image-svg" > &example1SVG; </img>
<!-- 解析されていない外部エンティティとして参照することもできます -->
<img title= "&example1SVGTitle;" data= "example1SVG" />
<!-- GIF 画像は解析できず、外部エンティティとしてのみ参照できます -->
<img title= "&example1GIFTitle;" data= "example1GIF" /> </sgml>
上記の例は、最初の例 (MIME タイプとしてローカルに解釈される相対 URI) のようにシステム識別子のみを指定するのではなく、SVG 1.1 ドキュメントの標準公開 FPI とシステム識別子 (標準 URI) を参照する「type-image-svg」という表記を示しています。この注釈は、「img」要素の解析されていない「type」属性内で直接参照されますが、その内容は取得されません。また、ベンダー固有のアプリケーション用に別の表記を宣言し、ドキュメント内の「sgml」ルート要素に注釈を付けます。どちらの場合も、宣言された名前の表記は、宣言された「type」属性で直接使用され、その内容は DTD で「NOTATION」属性タイプを使用して指定されます (この「type」属性は、「sgml」要素と「img」要素の両方に対して宣言されます)。
ただし、「img」要素の「title」属性は、宣言で注釈を定義していない内部エンティティ「example1SVGTitle」を指定するため、検証パーサーによって解析され、エンティティ置換テキストは「example1.svg のタイトル」になります。
「img」要素のコンテンツは、別の外部エンティティ「example1SVG」を参照します。このエンティティの宣言でも表記法が定義されていないため、検証パーサーによって解析され、エンティティ置換テキストは、定義された SYSTEM 識別子「example1.svg」(相対 URI としても解釈されます) によって特定されます。「img」要素の有効なコンテンツは、この 2 番目の外部リソースのコンテンツです。GIF 画像との違いは、SVG 画像は DTD の宣言に従って SGML ドキュメント内で解析されるのに対し、GIF 画像は「data」属性 (値タイプは不透明なエンティティ) を介して不透明な外部オブジェクト (SGML では解析できません) として参照される点です。
ENTITY 属性の値には、1 つの表記法名のみを指定できます (SGML、XML 1.0、または XML 1.1 では、同じ宣言された外部 ENTITY 内で複数の表記法名をサポートしていないため、別の属性が必要です)。ただし、ENTITIES タイプで宣言された属性では、複数の外部エンティティを参照できます (名前のスペース区切りリスト内)。この場合、名前付き外部エンティティはそれぞれ独自の表記法でも宣言されます。
XML および SGML パーサーの場合も表記法は完全に不透明であるため、参照する可能性のある外部エンティティの種類によって区別されることはありません (これらのパーサーの場合、表記法にはパブリック識別子 (FPI) および/またはシステム識別子 (URI) に関連付けられた一意の名前があるだけです)。
一部のアプリケーション (XML または SGML パーサー自体ではない) では、"URN:''name''"URI を指定できる場所であればどこでも、標準の CDATA 属性の値に名前を指定することにより、間接的に表記法を参照できます。ただし、この動作はアプリケーション固有であり、アプリケーションが既知の URN のカタログを保持して、標準の SGML または XML パーサーで解析された表記法に解決する必要があります。この使用法では、表記法は外部エンティティとして保存された DTD でのみ定義され、ドキュメントの外部サブセットとしてのみ参照されるため、これらのドキュメントは表記法を直接サポートしない検証 XML または SGML パーサーとの互換性を維持できます。
次の理由により、HTML や XHTML および SVG の基本プロファイルでは表記法は使用されません。
- これらの標準ドキュメント タイプで使用されるすべての外部エンティティは、標準 DTD で CDATA タイプを使用して宣言された単純な属性によって参照されます (アンカー "a" 要素の "href" 属性や、イメージ "img" 要素の "src" 属性など、その値は URI として解釈され、パブリック識別子のカタログ (つまり、既知の FPI) は必要ありません)。
- 追加のメタデータのすべての外部エンティティは、次のいずれかによって参照されます。
- 追加の属性(外部エンティティのMIMEタイプを示すtypeや、エンコードを示すcharset属性など)
- 独自の属性内の追加要素(HTML および XHTML のリンクやメタなど)
- XML および XHTML の標準疑似属性 ( xml:lang、または名前空間宣言のxmlnsおよびxmlns:*など)。
SGML または XML 1.0 または XML 1.1 パーサーを検証する場合でも、宣言された表記法の FPI および/または URI によって参照される外部エンティティは、パーサー自体によって自動的に取得されません。代わりに、これらのパーサーは、解析された SGML または XML ドキュメントで見つかった表記法に関連付けられた解析された FPI および/または URI を、DTD で宣言されたすべての表記法名を含む辞書の機能とともにアプリケーションに提供します。これらの検証パーサーは、表記法名宣言の一意性もチェックし、一部の表記法名が DTD またはドキュメント本体のどこかで使用されているが宣言されていない場合は検証エラーを報告します。
- アプリケーションがいずれの表記も使用できない場合 (または FPI や URI が不明であるかローカル カタログでサポートされていない場合)、これらの表記はアプリケーションによって暗黙的に無視されるか、アプリケーションによってエラーが通知される可能性があります。
- それ以外の場合は、アプリケーションがそれらをどのように解釈するかを独自に決定し、外部エンティティを取得して個別に解析する必要があります。
- このような解釈、取得、または個別の解析が失敗した場合、アプリケーションはエラーを通知することがあります。
- アプリケーションがエラーを通知する可能性のある認識されない表記法は、それらを使用する検証済みドキュメントの解釈をブロックしてはなりません。
XML DTD とスキーマ検証
XML DTD 構文は、いくつかのXML スキーマ言語の 1 つです。ただし、多くのスキーマ言語は、XML DTD を完全に置き換えるものではありません。特に、XML DTD では、DTD のない XML には直接同等のものがないエンティティと表記法を定義できます (内部エンティティと解析可能な外部エンティティは XML スキーマ言語の一部ではないため、および他の解析されない外部エンティティと表記法には、ほとんどの XML スキーマ言語で単純な同等のマッピングがないため)。
ほとんどの XML スキーマ言語は、要素宣言と属性リスト宣言の単なる代替であり、非検証XML パーサーを使用して XML ドキュメントを解析できるようになります(外部 DTD サブセットの唯一の目的がスキーマの定義である場合)。さらに、これらの XML スキーマ言語のドキュメントは個別に解析する必要があるため、これらの言語では XML ドキュメントのスキーマを純粋なスタンドアロン モードで検証することは実際には不可能です。解析された XML ドキュメントで使用され、別の言語で検証されているスキーマを ( XML カタログを使用して) 少なくとも識別するには、ドキュメント タイプ宣言が必要です。
よくある誤解として、検証を行わないXML パーサーは文書型宣言を読み取る必要がないというものがありますが、実際には、文書型宣言は正しい構文と宣言の妥当性についてスキャンする必要があり、パーサーは内部サブセット内のすべてのエンティティ宣言を解析し、文書型宣言内または文書本体内のどこかに出現する内部エンティティの置換テキストを置き換える必要があります。
ただし、非検証パーサーは、解析可能な外部エンティティ(外部サブセットを含む)を読み取らないことを選択でき、要素宣言および属性リスト宣言で定義されたコンテンツ モデルの制限を尊重する必要はありません。
XML 文書が解析可能な外部エンティティ (指定された外部サブセット、または内部サブセットで宣言された解析可能な外部エンティティを含む) に依存している場合は、standalone="no"XML 宣言でアサートする必要があります。検証 DTD は、指定された外部サブセットを取得するためにXML カタログを使用して識別できます。
以下の例では、XML ドキュメントはstandalone="no"ドキュメント タイプ宣言に外部サブセットがあるため、 で宣言されています。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE people_list SYSTEM "example.dtd">
<people_list />
XML 文書型宣言に外部サブセットの SYSTEM 識別子が含まれている場合、スタンドアロンとして安全に処理することはできません。URI を取得する必要があります。そうしないと、内部サブセットまたは文書本体の有効な XML 構文を正しく解析するために定義が必要となる可能性のある、不明な名前付き文字エンティティが存在する可能性があります (XML 構文の解析は通常、すべての名前付きエンティティの置換後に実行されますが、XML で事前定義され、XML 文書を語彙トークンに解析した後に暗黙的に置換される 5 つのエンティティは除きます)。PUBLIC 識別子のみが含まれている場合は、 XML プロセッサがローカル カタログでこの PUBLIC 識別子を認識し、そこから関連する DTD エンティティを取得できる場合は、スタンドアロンとして処理できます。
XML DTD スキーマの例
人物リストのスキーマを記述する非常に単純な外部 XML DTD の例は次のようになります。
<!ELEMENT people_list (人)* >
<!ELEMENT person (名前、 生年月日?、 性別?、 社会保障番号?) >
<!ELEMENT name ( #PCDATA ) >
<!ELEMENT birthdate ( #PCDATA ) >
<!ELEMENT gender ( #PCDATA ) >
<!ELEMENT socialsecuritynumber ( #PCDATA ) >
これを1行ずつ見てみましょう:
people_listは有効な要素名であり、そのような要素のインスタンスには任意の数のperson要素が含まれます。 は、要素内に 0 個以上の要素*が存在する可能性があることを示します。personpeople_listpersonは有効な要素名であり、そのような要素のインスタンスには という名前の要素が 1 つ含まれ、その後に (オプション)、(これもオプション)、 (これもオプション) というname名前の要素が続きます。 は、要素がオプションであることを示します。要素名への参照には がないため、要素には要素が含まれている必要があります。birthdategendersocialsecuritynumber?name?personnamenameは有効な要素名であり、そのような要素のインスタンスには「解析された文字データ」(#PCDATA) が含まれます。birthdate有効な要素名であり、そのような要素のインスタンスには解析された文字データが含まれます。gender有効な要素名であり、そのような要素のインスタンスには解析された文字データが含まれます。socialsecuritynumber有効な要素名であり、そのような要素のインスタンスには解析された文字データが含まれます。
この DTD を使用し、それに準拠する XML ファイルの例を以下に示します。ここでは、SYSTEM 指定子と URI を介して、DTD が外部サブセットとして参照されています。相対 URI 参照「example.dtd」で DTD を識別できることを前提としています。「!DOCTYPE」の後の「people_list」は、ルート タグ、つまり DTD で定義されている最初の要素が「people_list」であることを示しています。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE people_list SYSTEM "example.dtd">
<people_list>
<person> <name> Fred Bloggs </name> <birthdate> 2008-11-27 </birthdate> <gender>男性</gender> </person> </people_list>
これを XML 対応ブラウザ( Internet ExplorerやMozilla Firefoxなど) でレンダリングするには、上記の DTD コンポーネントをexample.dtdというテキスト ファイルに貼り付けて保存し、XML ファイルを別の名前のテキスト ファイルに貼り付けて保存し、ブラウザで XML ファイルを開きます。ファイルは両方とも同じディレクトリに保存する必要があります。ただし、多くのブラウザは XML ドキュメントが DTD のルールに準拠しているかどうかをチェックしません。ブラウザは DTD が構文的に正しいかどうかをチェックするだけで済みます。セキュリティ上の理由から、ブラウザが外部 DTD を読み取らないように選択する場合もあります。
同じ DTD を、ドキュメント タイプ宣言で [角括弧] で囲むことによって、XML ドキュメント自体に内部サブセットとして直接埋め込むこともできます。その場合、ドキュメントは外部エンティティに依存せず、スタンドアロン モードで処理できます。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE people_list [
<!ELEMENT people_list (person*)>
<!ELEMENT person (name, birthdate?, gender?, socialsecuritynumber?)> <!ELEMENT name (#PCDATA)> <!ELEMENT birthdate (#PCDATA)> <!ELEMENT gender (#PCDATA)> <!ELEMENT socialsecuritynumber (#PCDATA)>
]>
<people_list>
<person> <name> Fred Bloggs </name> <birthdate> 2008-11-27 </birthdate> <gender>男性</gender> </person> </people_list>
代替案
DTD の代替手段 (スキーマを指定するためのもの) が利用可能です:
- XML スキーマはXML スキーマ定義 (XSD) とも呼ばれ、W3C で勧告の地位を獲得しており[8]、型付けが強力で Java 宣言とのラウンドトリップが容易なため、「データ指向」(つまり、トランザクション非出版) XML でよく使用されています。[要出典]出版業界のほとんどは、XSD の複雑さが増しても特にメリットがないことに気付いており[要出典]、そのため DTD の方が依然として人気があります。XML スキーマ定義自体は XML ドキュメントですが、DTD は XML ドキュメントではありません。
- DSDLの一部であるRELAX NGは、ISO国際標準です。[9] XSDよりも表現力が豊かで[引用が必要]、よりシンプルな構文を提供しますが[引用が必要]、商用ソフトウェアのサポートは遅れています。
安全
XML DTDは、指数関数的に拡大するネストされたエンティティを定義したり、XMLパーサーを決して戻らない外部リソースに送信したりすることで、サービス拒否(DoS)攻撃を作成するために使用される可能性があります。[10]
このため、.NET FrameworkではDTD解析を禁止またはスキップできるプロパティが提供されており[10]、Microsoft Officeアプリケーションの最新バージョン(Microsoft Office 2010以降)ではDTD宣言を含むXMLファイルを開くことを拒否します。
参照
- JATS (ジャーナル記事タグスイート)
- セマンティックウェブ
- XML スキーマ (W3C)
- XML スキーマ言語の比較– 他の XML スキーマ言語との比較。
参考文献
- ^ 「DTD 入門」。
- ^ "doctypedecl".拡張マークアップ言語 (XML) 1.1 . W3C.
- ^ Watt, Andrew H. (2002). Sams が 10 分で XML を教える. Sams Publishing. ISBN 9780672324710。
- ^ 属性リスト宣言、拡張マークアップ言語(XML) 1.1 の仕様、W3C。
- ^ 「DTD エンティティ」。DTD チュートリアル。W3Schools。
- ^ 表記法宣言、拡張マークアップ言語(XML) 1.0 の仕様、W3C。
- ^ 表記法宣言、拡張マークアップ言語(XML) 1.1 の仕様、W3C。
- ^ 「XML スキーマ パート 1: 構造 (第 2 版)」。W3C。2004 年。2022 年 1 月 2 日閲覧。
- ^ 「ISO/IEC 19757-2:2008 - 情報技術 - 文書スキーマ定義言語 (DSDL) - パート 2: 正規文法ベースの検証 - RELAX NG」。ISO。2011年 5 月 17 日閲覧。
- ^ ab Bryan Sullivan (2009 年 11 月)。「XML サービス拒否攻撃と防御」。MSDN マガジン。2013 年 10 月 21 日閲覧。
外部リンク
- W3.org の Extensible Markup Language (XML) 1.0 (第 4 版) からの XML ドキュメント タイプ宣言の定義
