![](catch.gif)
XMLマスターへの道
〜「XMLマスター:ベーシック」試験対策〜
第5回 valid XMLとDTDの関係
武田栄子
ウチダ人材開発センタ
2003/3/11
今回は、XML文書のスキーマを定義する手段の1つであるDTD(Document Type Definition)について解説します。また、前回「第4回 すべてのXML文書は整形式である」で予習問題として出題した下記の問題の解答も紹介します。
今回の問題 | |||
(Q1) DTDについて正しく説明しているものをすべて選択してください。
|
|||
(Q2) 以下のDTDに妥当なXML文書をすべて選択してください。
|
今回は、この問題に解答するうえで必要な知識となる5つの内容
- スキーマ定義言語とDTD
- valid XML(妥当なXML)
- DTDの記述場所
- 要素型宣言
- 属性リスト宣言
について前回でも例として扱った社員リストを基に解説することで、XMLマスター:ベーシック試験に対応できるようにします。DTDも出題割合の高いカテゴリなので、サンプルファイルなどで動作を試しながら学ぶとよいでしょう。
下記に、説明で使うXML文書のサンプルを示します。
<?xml version="1.0" encoding="Shift_JIS"?> |
リスト1 社員データのサンプル(test5_01.xml) |
リスト1の文書本体を見ると、いくつかの規則に従っていることが分かります。この規則を文章で説明すると、次のようになります。
● 社員データには、1人以上の社員情報がある |
● 社員情報には、付加情報として社員番号がある |
● この社員情報には、社員名と所属している部署名が含まれる |
● 社員名、部署名の順で出現する |
● 社員名、部署名は文字データで記述されている |
さらに、リスト1を図式化したものが図1です。
|
図1 リスト1を図式化すると上記のような構造となる |
では、test5_01.xmlを書き換えて、わざと「部署情報がない」「上司の名前も社員情報に含まれている」など、前述の規則に従っていないXML文書へ変更した場合どのようになるでしょうか。
<?xml version="1.0" encoding="Shift_JIS"?> |
リスト2 リスト1の規則に従っていないXML文書へ変更(test5_02.xml) |
![]() |
画面1 test5_02.xmlをIEで開いたが、特にエラーとならない |
Internet Explorer(以後IE)で開いてみても特にエラーとならないことが分かります。というのも、前回解説したように、整形式規約を満たしていればXML文書としては成立するため、エラーを出す理由がないからです。
しかし、XMLに限らず、データをアプリケーションなどで読み込ませて活用したいときには、記述されているデータに規則性がある方がずっと扱いやすくなります。例えばXMLで記述された受発注書を企業間でやりとりするような場合、それぞれが情報を扱いやすいように、各項目の名前や順番、どんな項目が必要か、といったデータの記述の仕方にある程度の規則を持たせる必要があるでしょう。
上記のように、要素や属性の名前、出現順などのことをXML文書の構造(スキーマ)と呼びます。そして、 そのスキーマを定義する言語として、XML 1.0の仕様では「DTD」が規定されています。
スキーマ定義言語にはそのほかにXML Schema、XDR、RELAX NGなどがありますが、XMLマスター:ベーシックで試験範囲となっているのはDTDとXML Schemaだけです。
■valid XML(妥当なXML)
前回、「XML文書を制約という観点からみると、well-formed XML(整形式なXML)以外にvalid XML (妥当なXML)があります」と説明しました。well-formed XMLは、スキーマ定義に従って記述されていてもいなくても構いません。一方で、スキーマ定義であるDTDが記述されたうえで、文書本体がそのDTDに従って記述されているXML文書を「valid XML」といいます。
well-formed XMLにもDTDを記述して構いませんが、DTDが記述されているだけではvalid XMLになりません(XML文書の本体がDTDに従っていなくてもwell-formed XMLにはなります。valid XMLでは本体がDTDに従っていなくてはなりません)。
では、DTDの記述方法を紹介しましょう。DTDは、XML宣言と文書本体の間に記述します。DTDにはコメントを記述することも可能なので、注釈を入れる場合に便利です。リスト1の規則を基に、test5_01.xmlにDTDを追加したものがリスト3のtest5_03.xmlです。
<?xml version="1.0" encoding="Shift_JIS"?> |
XML宣言 (任意) |
<!DOCTYPE 社員データ [ |
DTD |
<社員データ> |
文書本体 (必須) |
リスト3 test5_01.xmlにDTDを追加。このXML文書はDTDのスキーマ定義を満たしているvalid XMLである(test5_03.xml) |
では、わざと規則に従っていないXML文書として作ったtest5_02.xmlにも、このDTDを追加してみます。それをIEで開くと、どのようになるでしょうか。
![]() |
画面2 test5_02.xmlにリスト4と同じDTDを追加しても、IEで開いたときにエラーとならない (test5_04.xml) |
エラーになりません。なぜエラーにならないのでしょうか。実は、XMLパーサはwell-formed XMLかどうかは解析しますが、文書本体がDTDに従っているかという妥当性の検証は任意となっています。
なお、今回XMLパーサとして使っているMSXMLは、本来DTDによる妥当性を検証する機能を持つXMLパーサですが、IEに組み込んで動作させる場合はDTDによる妥当性を検証しません。IE上でDTDによる妥当性を検証したい場合、Internet Explorer Tools for Validating XML and Viewing XSLT Output (以後、IE for Validating XML) などの検証用ツールを使うと便利です。
IE for Validating XMLで妥当性を検証する場合、ブラウザウィンドウ内で右クリックし、[validate XML] を実行します。DTDのスキーマ定義に妥当なtest5_03.xmlを検証すると、画面3のように検証が成功した旨のメッセージが返ってきます。
|
画面3 DTDのスキーマ定義に、妥当なtest5_03.xmlをIE for Validating XMLで検証したとき |
それに対して、DTDのスキーマ定義に妥当でないtest5_04.xmlを検証すると、画面4のように検証がエラーになった旨のメッセージが返ってきます。
|
画面4 DTDのスキーマ定義に妥当でないtest5_04.xmlをIE for Validating XMLで検証したとき |
DTDを使うことで、XML文書のデータに規則性を持たせることができますが、同じスキーマ定義を複数のXML文書へ何度も記述するのは非効率ですし、スキーマ定義に変更があった場合すべてのファイルへ変更を反映しなければいけません。では、どのようにすればいいでしょうか。
DTDは、対象とするXML文書内もしくは、対象とするXML文書とは異なるファイルのいずれにも記述できます。XML文書内に記述したDTDを「内部サブセット」と呼び、対象となるXML文書とは異なるファイルに記述されたDTDを「外部サブセット」と呼びます。いままで紹介してきたtest5_03.xml、test5_04.xmlでは、内部サブセットでDTDが定義されていました。
外部サブセットのメリットとしては、1つのスキーマ定義を複数のXML文書へ適用させることができる点です。企業間取引、標準化団体などで取り決めた記述ルールに従った多数のXML文書を記述する場合に有用です。
|
図2 内部サブセットと外部サブセット |
内部サブセットと外部サブセットでは、構文が多少異なるので以下にまとめました。
<!DOCTYPE ルート要素名 [この中にDTDを記述]> |
内部サブセットの構文 |
<!DOCTYPE ルート要素名 SYSTEM
"外部サブセットが記述されているファイルのURI"> |
外部サブセットの構文 : SYSTEMキーワードを使う場合、双方の合意を意味する |
<!DOCTYPE ルート要素名 PUBLIC
"公開識別子" "外部サブセットのURI"> |
外部サブセットの構文 (標準化団体などのDTDを利用する場合など) |
下記のリスト4が、test5_03.xmlを外部サブセットへ変更したときのサンプルです。
<?xml
version="1.0" |
<?xml version="1.0" |
<!DOCTYPE 社員データ |
<!ELEMENT
社員データ (社員+)> |
<社員データ> |
|
リスト4 test5_03.xmlを外部サブセットへ変更(左がtest5_05.xml、右がtest5_05.dtd) |
なお、test5_05.dtdのようにXML文書以外でXML宣言を行っているものを「テキスト宣言」と言います。テキスト宣言では、DTDファイルの文字エンコーディングをencodingで指定します。XML文書と外部サブセットで記述したDTDファイルとの文字エンコーディングが異なっていても構いません。文字エンコーディングが異なるファイル(test5_06.xml、test5_06.dtd)を用意しているので、XMLパーサで確認してみてください。
ここでは、DTDの内容について解説しましょう。DTDの中で、要素を定義するのが「要素型宣言」です。文書本体の中で出現する可能性のある要素を宣言します。同じ要素名の要素型宣言を重複して定義することはできません。これは、内部サブセット、外部サブセットそれぞれに記述した場合も同様です。
<!ELEMENT 要素名 内容モデル> |
要素型宣言の構文 |
内容モデルには、要素の内容が文字データか子要素か、子要素の場合は出現順序や出現回数を指定します。内容モデルを以下にまとめました。こちらもXMLマスター:ベーシックでポイントになる個所なので、前述のIE for Validating XMLを使って実機で学習されることをお勧めします。
種類 | DTDの記述例 | 説明 |
(#PCDATA) | <!ELEMENT a (#PCDATA)> | 内容が文字データである |
記号なし | <!ELEMENT a (b)> | 必ず1回 子要素が出現する |
, | <!ELEMENT a (b, c)> | 左から記述された順に子要素が出現する |
| | <!ELEMENT a (b | c)> | | で区切られた子要素のうち、いずれか1つが出現する |
? | <!ELEMENT a (b?)> | 子要素は0回または1回出現する |
+ | <!ELEMENT a (b+)> | 子要素は1回以上出現する |
* | <!ELEMENT a (b*)> | 子要素は0回以上任意の回数で出現する |
ANY | <!ELEMENT a ANY> | DTDで定義されている要素であれば、どんな順序、どんな回数出現してよい |
EMPTY | <!ELEMENT a EMPTY> | 要素aは空要素である |
表1 内容モデル |
そのほか、要素の内容として文字データと子要素が混在している「混合内容」がありますが、こちらはXML 1.0仕様および書籍などでご確認ください。
属性を定義するのが「属性リスト宣言」です。属性リスト宣言の場合、ある要素に同じ属性を重複して記述すると、先に記述されている方を有効とします。さらに、内部サブセット、外部サブセットへそれぞれ記述できますが、内部サブセットに記述された方を有効とします。
<!ATTLIST 要素名 属性名 属性の型
デフォルト値> |
属性リスト宣言の構文 |
属性リスト宣言で指定できる属性の型を表2にまとめました。
型 | 説明 |
CDATA | 任意の文字データ |
ID | 文書内で一意な値を持つ名前 |
IDREF | ID型で設定された属性値を参照する |
IDREFS | ID型で設定された属性値を複数参照する (属性値は空白で区切る) |
ENTITY | 外部実体を参照する(属性値は空白で区切る) |
ENTITIS | 複数の外部実体を参照する |
NMTOKEN | 名前として使える文字 (2文字目以降で使える文字も属性値の先頭へ記述できる) |
NMTOKENS | NMTOKENの複数形(属性値は空白で区切る) |
列挙型 | 属性値の候補値を | で区切る |
表2 属性リスト宣言で指定できる型 |
今回は、列挙型に焦点を絞って解説します。列挙型は属性値として記述できるものをパイプ(|)で区切って指定します。文書本体で属性値を記述するときは一重引用符(')または二重引用符(")でくくりますが、カッコ内で属性の候補値を列挙するときは引用符のくくりは不要です。XML文書中で候補値以外の値を記述すると、valid XMLとはいえなくなります。 例をリスト5、6で示します。
<?xml version="1.0"
encoding="Shift_JIS"?> root attr="02"/> |
リスト5 候補値の属性値を記述しているので、valid XMLである(test5_07.xml) |
<?xml version="1.0"
encoding="Shift_JIS"?> root attr="03"/> |
リスト6 候補値以外の属性値を記述しているので、valid XMLではない(test5_08.xml) |
次に、デフォルト値について解説します。デフォルト値には、属性が必須か、省略可能か、固定値を設定するか、などを記述します。
種類 | 説明 |
#IMPLIED | 属性は省略可能 |
#REQUIRED | 属性は必須 |
"デフォルト値" | 属性値が記述されていなかったときに渡されるデフォルト値 |
#FIXED "デフォルト値" | 固定値を指定 |
表3 属性リスト宣言で指定できるデフォルト値 |
例えば、リスト7のように属性リスト宣言ではデフォルト値を指定しているが、文書本体では属性・属性値の記述がない場合、どのようになるでしょうか。
<?xml version="1.0"
encoding="Shift_JIS"?> root/> |
リスト7 文書本体に属性の記述はないけれど、デフォルト値が指定されている場合…… (test5_09.xml) |
|
画面5 XMLパーサによってデフォルトの属性値が渡される |
XML 1.0仕様では、属性が省略されている場合、XMLパーサはその属性が宣言されたデフォルト値を付けて動作するように規定しています。#FIXEDのときも同じようにデフォルト値がXMLパーサによって渡されますが、#REQUIREDは属性を省略することを許可しないため、省略されたXML文書はwell-formed XMLであっても、valid XMLではありません。
<?xml version="1.0" encoding="Shift_JIS"?> |
リスト8 文書本体に属性の記述はないけれど、デフォルト値が指定されている場合……(test5_10.xml) |
![]() |
画面6 #REQUIREDが指定された場合、デフォルト値は渡されずvalid XMLとならない |
ただし、DTDの場合「社員番号は正の整数値である」「社員情報は1回以上5回以下の範囲で出現しなければならない」など、データの型や出現回数などを細かく定義できないのが欠点です。こうしたDTDの欠点を解消するための仕組みとして、XML SchemaがW3Cより勧告されています。XML Schemaについては、次回解説します。
■今回の問題の解答
今回の問題の解答は次のとおりです。先述の解説を読み直し、試験に向けて備えてください。
(Q1) DTDについて正しく説明しているものをすべて選択してください。
答えは(a)(c)(d)(f)です。それぞれの選択肢についての解説は、下記を参照してください。
(a) : (参考になる解説 「スキーマ定義言語とDTD」)
(b) : (参考になる解説 「スキーマ定義言語とDTD」)
(c) : (参考になる解説 「DTDの記述場所」)
(d) : DTDでも大文字小文字は識別されます。SGMLのときから使われていたDOCTYPE、ELEMENTなどのキーワードは大文字で記述します。
(e) : Q5_1e.xml、Q5_1e.dtdで妥当性を検証してみましょう(参考になる解説
「DTDの記述場所」)。
(f) : Q5_1f.xml、Q5_1f.dtdでどちらのデフォルト値が有効になっているか確認しましょう(参考になる解説
「DTDの記述場所」)。
(g) : 外部サブセットを使うときのキーワードは両者間合意のSYSTEMか、標準化団体が策定したDTDであることを示すPUBLICのいずれかです。PRIVATEというキーワードはありません(参考になる解説
「DTDの記述場所」)。
(Q2) 以下のDTDに妥当なXML文書をすべて選択してください。
答えは(c)(d)(i)(k)です。このDTDで記述されたスキーマ定義を文章で説明すると、次のようになります。
- 要素rootは子要素として1回のみ出現する要素A、または1回以上出現する要素Bを子要素として含める。
- 要素Aの内容は文字データで、属性aを付加情報として持つことができる。
- 属性aの値は12、34、56のいずれかであり、デフォルト値は12である。
- 要素Bの内容は文字データで、属性bを付加情報として持つことができる。
- 属性bの値はID型であり、この属性は必ず出現しなければならない 。
この問題に対応する解説は、「要素型宣言」「属性リスト宣言」が参考になります。
(e) : 要素の中に同じ属性を記述することはできません。このデータはwell-formed XMLではないため、当然valid XMLでもありません。
なお、Q2の選択肢ファイルを用意していますので、DTDの記述に妥当なXML文書がどれか確認してみるとよいでしょう。
前回同様、記事の最後に「まとめノート」を用意しました。このまとめノートには、試験対策のポイント、出題範囲となる仕様、参考になる@ITの記事のリンクをまとめています。自習のときに使う参考ページとして、お役立てください。
そして、次回のための予習問題を掲載します。次回はこの問題について解説していく予定です。
予習問題 | |||
(Q1) 以下のXML文書について正しく説明しているものを選択してください(左端の行番号はXML文書に含まれません)。
|
|||
(Q2) 要素aの内容が10以上20未満となるようにXML Schemaで記述するときに必要な制約ファセットをすべて選択してください。
|
|||
(Q3) DOMについて正しく説明しているものをすべて選択してください。
|
○今回の試験対策のポイント
- スキーマ定義言語
- DTD
- valid XML(妥当なXML)
- DTDの記述場所
- 要素型宣言
- 内容モデル
- 属性リスト宣言
- 属性の型
- デフォルト値
○今回の学習内容で出題範囲となる仕様
○今回の学習内容で実機確認を行うときに役立つフリーツール
- Internet Explorer 5.0 以上
- サクラエディタ
- MSXML
Parser 3.0 Service Pack 2 Release
※ 別途、Xmlinst.exe Replace Mode Toolが必要になる場合あり(詳細は、Microsoft XML Parser Version 3.0 Releaseの新機能をご参照ください) - Internet Explorer Tools for Validating XML and Viewing XSLT Output
○今回の学習内容で参考になる@ITの記事
- 技術者のためのXML再入門 第4回 XML文書の構造を詳しく見ていく
- 技術者のためのXML再入門 第5回 XML文書のカタチを決めるDTD
- やさしく読む「XML 1.0勧告」 第4回 XML仕様書で使われる言葉の意味
- XMLを学ぼう 第4回 スキーマ言語「DTD」の機能と役割
- XMLを学ぼう 第5回 DTDを読んでみよう
- XMLを学ぼう 最終回 XML仕様書の構造と読み方
- XMLの基礎を理解する10のポイント ポイント#3 XML宣言とDTDと本体
- XMLの基礎を理解する10のポイント ポイント#5 整形式な文書と妥当な文書
- XMLの基礎を理解する10のポイント ポイント#8 スキーマが活用範囲を広げる
- Ask XML Expert スキーマっていったい何?どんな役割をするものですか?
- Ask XML Expert DTDが必要なときとは?
○今回の学習内容で参考になるXML用語集 (@IT XML用語事典より)
- DDML (Document Definition Markup Language)
- DTD
- RELAX
- SOX(Schema for Object-Oriented XML)
- XDR (XML-Data Reduced)
- XML-Data
- XML Schema
- XMLパーサ
- スタンドアロン文書
- 整形式のXML文書 (Well-Formed XML Document)
- 妥当なXML文書 (Valid XML Document)
- 混合内容
- 実体 (Entity)
- 実体参照
- パラメタ実体
- 解析対象実体
- 解析対象外実体
- 条件付きセクション
- 記法 (Notation)
- スキーマ (Schema)
- バリデータ
- バリデート
![]() |
(6)模擬問題:XMLの基本![]() |
![]() |
連載:XMLマスターへの道 |
- QAフレームワーク:仕様ガイドラインが勧告に昇格 (2005/10/21)
データベースの急速なXML対応に後押しされてか、9月に入って「XQuery」や「XPath」に関係したドラフトが一気に11本も更新された - XML勧告を記述するXMLspecとは何か (2005/10/12)
「XML 1.0勧告」はXMLspec DTDで記述され、XSLTによって生成されている。これはXMLが本当に役立っている具体的な証である - 文字符号化方式にまつわるジレンマ (2005/9/13)
文字符号化方式(UTF-8、シフトJISなど)を自動検出するには、ニワトリと卵の関係にあるジレンマを解消する仕組みが必要となる - XMLキー管理仕様(XKMS 2.0)が勧告に昇格 (2005/8/16)
セキュリティ関連のXML仕様に進展あり。また、日本発の新しいXMLソフトウェアアーキテクチャ「xfy technology」の詳細も紹介する
![]() |
|
|
|
![]() |