文書型定義(DTD )とは、 SGMLファミリーのマークアップ言語(GML、SGML、XML、HTML )の文書型を定義する一連のマークアップ宣言を含む仕様ファイルです。DTD仕様ファイルは、文書の検証に使用できます。
DTDは、XMLドキュメントの有効な構成要素を定義します。検証済みの要素と属性のリストを使用してドキュメント構造を定義します。DTDは、XMLドキュメント内にインラインで宣言することも、外部参照として宣言することもできます。[ 1 ]
DTD は、 ISO SGML 標準化作業の一部として定義されたより大きなセットから派生したXML および HTML 文字エンティティ参照など、特別な公開文字を必要とするアプリケーションで引き続き使用されます。XMLはSGML DTDのサブセットを使用します。名前空間対応 DTD を作成する試みは ISO DSDLのパート 9 として開発されていましたが、これは最終的に撤回されました。[ 2 ]
2009年現在近年では、XML名前空間に対応した新しいスキーマ言語( W3C XML SchemaやISO RELAX NGなど)が、XML構造を検証するより良い方法としてDTDに取って代わっています。
DTD は、文書型宣言(DOCTYPE)によって XML または SGML 文書に関連付けられます。DOCTYPE は、XML 文書の先頭付近にある構文断片doctypedeclに現れます。 [ 3 ]この宣言により、文書が参照される DTD によって定義された型のインスタンスであることが確立されます。
DOCTYPEは2種類の宣言を行います。
内部サブセット内の宣言は、文書自体のDOCTYPEの一部を構成します。外部サブセット内の宣言は、別のテキストファイルに格納されます。外部サブセットは、公開識別子および/またはシステム識別子を介して参照できます。文書読み取りプログラムは、外部サブセットを読み込む必要がない場合があります。
DTD 内で外部サブセットを参照する有効な SGML または XML 文書、あるいは本文にDTD 内で宣言された解析済みの外部エンティティ(内部サブセット内で宣言されたものを含む) への参照が含まれる文書は、 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ドキュメントの構造で許可される要素タイプ、属性リスト、エンティティ、および表記法を宣言します。 [ 4 ]
要素型宣言は、要素とその可能な内容を定義します。有効なXML文書には、DTDで定義された要素のみが含まれます。
さまざまなキーワードや文字によって、要素の内容が指定されます。
EMPTY定義された要素がコンテンツを一切許可しないこと、つまり、テキスト要素を含むいかなる子要素も持つことができないことを指定するため(空白文字がある場合は無視されます)。ANY定義された要素が制限なくあらゆるコンテンツを許可すること、つまり、任意の数(なしを含む)および種類の子要素(テキスト要素を含む)を持つことができることを指定するため。(#PCDATA): 歴史的には解析された文字データを意味し、これはコンテンツ内に許可されるテキスト要素が 1 つだけであることを意味します (量指定子は許可されません)。(#PCDATA|''elementname''|...)*: 2 つ以上の子要素 (テキスト要素または指定された名前の要素のみを含む) を、コンテンツ内で任意の順序および出現回数で使用できます (括弧で囲まれ、「|」パイプ文字で区切られ、必要な「*」量指定子で終了する排他的リスト内)。,とは、1 つ以上のコンテンツ パーティクルの順序付きリスト (括弧で囲まれ、「 」 カンマ文字で区切られる) を意味します。すべてのコンテンツ パーティクルは、定義された要素のコンテンツ内で、指定された位置と相対的な順序で、直接の子として連続して出現する必要があります。|とは、 2 つ以上のコンテンツ粒子の相互排他的なリスト (括弧で囲まれ、「 」パイプ文字で区切られる) を意味します。これらのコンテンツ粒子のうち、同じ位置にある定義済み要素のコンテンツには 1 つだけ出現できます。+項目が1回以上出現する必要があることを指定するため。各出現の実際の内容は異なっていても構わない。*出現回数が任意(0回以上)であることを指定する場合。この項目はオプションであり、各出現の実際の内容は異なっていても構いません。?複数回出現してはならないことを指定する場合、この項目はオプションです。例えば:
<!ELEMENT html ( head , body ) > <!ELEMENT p ( #PCDATA | p | ul | dl | table | h1 | h2 | h3 )* >要素型の宣言は、検証を行わないSGMLおよびXMLパーサーでは無視されます(この場合、解析されたドキュメント内では、任意の順序で、任意の回数の要素が受け入れられます)が、これらの宣言は形式と有効性についてチェックされます。
属性リストは、特定の要素型に対して、その型に関連付けられる可能性のあるすべての属性のリストを指定します。各属性について、以下の内容が含まれます。
例えば:
<!ATTLIST img src CDATA #必須id ID #暗黙的sort CDATA #固定"true" print ( yes | no ) "yes" >SGMLとXMLの両方でサポートされている属性タイプをいくつか紹介します。
CDATAIDxml:idDTD での宣言を必要とせずに、このタイプの標準擬似属性 " " を事前に定義しているため、一意性制約は、XML ドキュメント内のどこかでこれらの定義された識別子が指定されている場合にも適用されます。IDREFまたはIDREFSIDDTD で型が宣言された属性を持つドキュメントで定義された一意の要素(または、擬似属性 " xml:id" を持つ XML ドキュメントで定義された一意の要素)を参照し、その実効値が同じ識別子である必要があります。NMTOKENまたはNMTOKENSENTITYまたはENTITIES(value1|...)|」パイプ文字で区切られる)のテキスト値のいずれかのみになります。列挙された各値は、単純な名前トークンでない場合は、'単一引用符'または"二重引用符で囲むことができます。"NOTATION (notation1|...)|」パイプ文字で区切られた表記名のリストのいずれか1つのみにすることができます。列挙された各表記名は、文書型宣言でも宣言されている必要があります。この型は HTML パーサーではサポートされていませんが、SGML および XML 1.0 または 1.1 (XHTML および SVG を含む) では有効です。デフォルト値は、属性が必ず存在する必要があるか(#REQUIRED)、存在しないか(#IMPLIED)、固定値を持つか(#FIXED)、または指定された属性が XML タグで省略された場合にデフォルト値としてどの値を使用するか("…") を定義できます。
属性リスト宣言は、検証を行わないSGMLおよびXMLパーサーでは無視されます(この場合、解析されたドキュメントのすべての要素内で任意の属性が受け入れられます)が、これらの宣言は依然として整形式性と有効性についてチェックされます。
エンティティはマクロに似ています。エンティティ宣言では、ドキュメント全体で保持される値が割り当てられます。一般的な用途としては、馴染みのない文字に対して数値文字参照よりも認識しやすい名前を付けることが挙げられます。 [ 6 ]エンティティは、XML テキストの可読性を向上させるのに役立ちます。一般的に、内部エンティティと外部エンティティの 2 種類があります。
内部エンティティ宣言の例(ここでは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" >これは、このタイプの外部画像のメディア タイプを宣言し、それを表記名「type-image-svg」に関連付けます。ただし、表記名は通常、表記を生成または使用するアプリケーションに固有の命名規則に従います。表記は、有効なコンテンツが外部エンティティであり、XML または SGML パーサーで使用されるカタログに登録された PUBLIC FPI、またはアプリケーションに依存する SYSTEM URI (ここでは相対 URI として解釈される MIME タイプですが、特定のレンダラーへの絶対 URI、または UUID などの OS 固有のオブジェクト識別子を示す URN である可能性があります) のいずれかである追加のメタデータとして解釈されます。
宣言された表記名は、少なくとも XML に準拠するためには、文書型宣言全体、つまり外部サブセットと内部サブセットの両方で一意でなければなりません。[ 7 ] [ 8 ]
表記法は、SGML または XML ドキュメントの本文に含まれる解析されていない外部エンティティに関連付けることができます。これらの外部エンティティのPUBLICまたはSYSTEMパラメータは、外部エンティティの解析されていないデータが格納されている FPI および/または URI を指定し、NDATAこれらの定義済みエンティティの追加パラメータは、追加の表記法 (つまり、ここでは実質的に 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 data= "example1SVG" /> </sgml>
SGML 文書の本文内では、これらの参照された外部エンティティ (名前が「&」と「;」で指定されている) は、通常の名前付きエンティティ (CDATA 値で定義) のように置き換えられるのではなく、個別の解析されていないトークンとして残されます。これらのトークンは、要素属性の値 (上記のように) として、または要素の内容内で使用できます。ただし、DTD が要素の宣言されたコンテンツ タイプまたは属性の宣言されたタイプ (ここでは属性ENTITYのタイプdata) でそのような外部エンティティを許可している場合、または SGML パーサーが内容を検証していない場合に限ります。
表記法は、要素を別の外部エンティティに関連付けることなく、追加のメタデータとして要素に直接関連付けることもできます。これは、要素の宣言内で 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 つの表記法のいずれかにのみ設定できます。 --> <!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>上記の例では、最初の例のようにシステム識別子だけを指定するのではなく、SVG 1.1 ドキュメントの標準パブリック FPI とシステム識別子 (標準 URI) を参照する「type-image-svg」という名前の表記法を示しています (最初の例では、相対 URI がローカルで MIME タイプとして解釈されました)。この注釈は、「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」属性(値の型は不透明な ENTITY)を介して不透明な外部オブジェクト(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の基本プロファイルでは表記法は使用されません。理由は以下のとおりです。
SGML、XML 1.0、またはXML 1.1の検証パーサーにおいても、宣言された表記法でFPIやURIによって参照される外部エンティティは、パーサー自体によって自動的に取得されるわけではありません。代わりに、これらのパーサーは、解析されたSGMLまたはXMLドキュメントで見つかった表記法に関連付けられた解析済みのFPIやURIをアプリケーションに提供するだけで、DTDで宣言されたすべての表記法名を含む辞書を提供する機能も備えています。また、これらの検証パーサーは表記法名の宣言の一意性をチェックし、DTDまたはドキュメント本文のどこかで使用されているにもかかわらず宣言されていない表記法名がある場合は、検証エラーを報告します。
XML DTD構文は、複数のXMLスキーマ言語の一つです。しかし、多くのスキーマ言語はXML DTDを完全に置き換えるものではありません。特に、XML DTDでは、DTDを使用しないXMLでは直接対応するものがないエンティティや表記を定義できます(内部エンティティや解析可能な外部エンティティはXMLスキーマ言語の一部ではなく、その他の解析されない外部エンティティや表記には、ほとんどのXMLスキーマ言語で単純な対応関係がないため)。
ほとんどの XML スキーマ言語は、要素宣言と属性リスト宣言の代替としてのみ機能し、外部 DTD サブセットの唯一の目的がスキーマの定義である場合、検証機能を持たないXML パーサーで XML 文書を解析することが可能になります。さらに、これらの 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の例としては、以下のようなものが考えられます。
<!ELEMENT people_list ( person )* > <!ELEMENT person ( name , birthdate ?, gender ?, socialsecuritynumber ?) > <!ELEMENT name ( #PCDATA ) > <!ELEMENT birthdate ( #PCDATA ) > <!ELEMENT gender ( #PCDATA ) > <!ELEMENT socialsecuritynumber ( #PCDATA ) >1行ずつ見ていきましょう。
people_listは有効な要素名であり、そのような要素のインスタンスには任意の数のperson要素が含まれます。 は、要素内に*0個以上のperson要素が存在する可能性があることを示しますpeople_list。personは有効な要素名であり、このような要素のインスタンスには、 という名前の要素が 1 つname、続いて という名前の要素birthdate(省略可能)、さらにgender(これも省略可能) とsocialsecuritynumber(これも省略可能) が含まれます。 は、?要素が省略可能であることを示します。要素名への参照にはnameがない?ため、person要素には要素が含まれている必要がありますname。nameは有効な要素名であり、そのような要素のインスタンスには「解析済み文字データ」(#PCDATA)が含まれます。birthdateは有効な要素名であり、そのような要素のインスタンスには解析された文字データが含まれます。genderは有効な要素名であり、そのような要素のインスタンスには解析された文字データが含まれます。socialsecuritynumberは有効な要素名であり、そのような要素のインスタンスには解析された文字データが含まれます。この DTD を使用し、それに準拠する XML ファイルの例を以下に示します。ここでは、DTD は SYSTEM 指定子と URI を介して外部サブセットとして参照されています。DTD は相対 URI 参照 "example.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> Male </gender> </person> </people_list>上記の DTD コンポーネントをexample.dtdという名前のテキストファイルに貼り付けて保存し、XML ファイルを別の名前のテキストファイルに保存して、XML ファイルをブラウザで開くことで、XML 対応ブラウザ( Internet ExplorerやMozilla Firefoxなど) でこれをレンダリングできます。両方のファイルは同じディレクトリに保存する必要があります。ただし、多くのブラウザは 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> Male </gender> </person> </people_list>DTD(スキーマを指定するためのツール)の代替手段は以下のとおりです。
XML DTDは、指数関数的に拡大するネストされたエンティティを定義したり、決して返さない外部リソースにXMLパーサーを送信したりすることで、サービス拒否攻撃を作成するために使用できます。 [ 11 ]
このため、.NET Framework には DTD の解析を禁止またはスキップできるプロパティが用意されており、[ 11 ] Microsoft Officeアプリケーション(Microsoft Office 2010以降)の最新バージョンでは、DTD 宣言を含む XML ファイルを開くことを拒否します。