xsd:any(1)

2003年5月18日(日)更新


■DTDのANY

たけち: 前回約束したように今日はxsd:anyの話をしようね。xsd:anyの話をする前に、まずはDTDのANYについて説明しておこうね。

さらら: DTDのANYってなに??

たけち: まず、DTDの要素型宣言の内容モデルの書き方にどんなものがあったか、ちょっとあげてみようか。

DTDの要素型宣言の内容モデルの書き方
<!ELEMENT a (b,c,d)>

<!ELEMENT a (b|c|d)>

<!ELEMENT a (#PCDATA)>

<!ELEMENT a (#PCDATA|b|c|d)*>

<!ELEMENT a EMPTY>

さらら: そういえば、こういうのを何度も見てきたわね。 (^ ^;

たけち: うん。ところで次のような書き方を見たことがある?

ANY要素
<!ELEMENT a ANY>

さらら: ANY ? こんな書き方って見たことがないわ。

たけち: そうだね。こういう書き方はめったに見られないからね。これはDTDで宣言された要素なら、何がここにどういう順番で出現してもかまわないという、何でもありの書き方なんだ。

さらら: え、そんな何でもありの内容モデルなの? (^ ^;)

たけち: そうなんだ。も少し具体的にみてみようか。次の例を見て。

さらら

XMLデータ例
<?xml version="1.0" encoding="Shift_JIS" ?>
<!DOCTYPE report SYSTEM "report.dtd">
<report>
    <heading>万葉集総論</heading>
    <author>万葉一郎</author>
    <regularContents>
    万葉の時代に触れるために、まず万葉集を開いてみよう。<lineBreak />
    そこでは、万葉の人達の息遣いが聞こえるようだ。
    </regularContents>
</report>

たけち: このXMLデータに合致するDTDは以下のように考えられるよね。

DTD: 上記XMLデータに対応
<!ELEMENT report (heading, author, regularContents)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT regularContents (#PCDATA | lineBreak)*>
<!ELEMENT lineBreak EMPTY>


■要素の追加や変更の可能性

さらら: そうね、これでいいと思うわ。

たけち: うん。で、ここでちょっと考えてみるね。regularContents要素の内容はテキストか、もしくは改行を示すlineBreak要素だけから成り立っているね。

さらら: えぇ。

たけち: でも、いまはとても簡単な構造になっているけど、もしかすると将来、paragraphという要素を使いたくなるかもしれないし、図を入れるためのimg要素を使いたくなるかもしれないね。そう思うと、どういうふうに将来拡張したくなるかわからないけれど、拡張しても、ゼロから作り直さなくても良いような仕掛けを作っておいた方がいいんじゃないだろうかと思うよね。

さらら: そうねぇ。そう言われればそうね。

たけち: そこで、このDTDを次のようにしてみよう。

たけち

DTD: 【report.dtd】
<!ELEMENT report (heading, author, (regularContents | extendContents))>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT regularContents (#PCDATA | lineBreak)*>
<!ELEMENT lineBreak EMPTY>
<!ELEMENT extendContents ANY>

たけち: ここでは、regularContents要素の代わりに、extendContents要素も使えるようにしておいたんだ。

さらら: えぇ。

たけち: で、
<!ELEMENT extendContents ANY>
とすることによって、このextendContents要素を使えば、後から要素を追加できるようになるんだね。

さらら: えっ? 具体的にどうするの?


■要素の追加

たけち: まず、次のようなXMLデータを考えてみるね。

XMLデータ例: 万葉歌
<?xml version="1.0" encoding="Shift_JIS" ?>
<!DOCTYPE report SYSTEM "extendReport.dtd">
<report>
    <heading>万葉集総論</heading>
    <author>万葉一郎</author>
    <extendContents>
        <paragraph>万葉の時代に触れるために、まず万葉集を開いてみよう。</paragraph>
        <paragraph>そこでは、<lineBreak />
        万葉の人達の息遣いが聞こえるようだ。</paragraph>

    </extendContents>
</report>

たけち

たけち: 後から、このようなparagraph要素extendContents要素の中で使いたくなった場合には、以下のように【extendReport.dtd】を書けばいいんだよ。

DTD例: 【extendReport.dtd】
<!ENTITY % reportDTD SYSTEM "report.dtd">
%reportDTD;
<!ELEMENT paragraph (#PCDATA | lineBreak)*>


■【xhtml1-transitional.dtd】を利用したDTDの例

さらら: あ、なるほど。report.dtd
<!ELEMENT paragraph (#PCDATA | lineBreak)*>
 という要素型宣言を加えるだけですむわけなのね!(^ ^)

たけち: そう。そこがこのDTDのANYの便利なところなんだ。

さらら: でも、たけちは、前に名前空間について説明したとき、「こんなXHTMLもどきの要素を使っちゃいけない」、って言っていなかったかしら? (^ ^;

たけち: あ、うぅぅ... これはあくまで例題を簡単にするための例題であって.......(^ ^;)
そうだね。じゃあ、あの時の【xhtml1-transitional.dtd】を利用してみようね。それを使うと、こういうDTDを作れるんだ。

さらら

DTD例: 【extendReport2.dtd】
<!ENTITY % reportDTD SYSTEM "report.dtd">
%reportDTD;
<!ENTITY % xhtml1-transitionalDTD SYSTEM "xhtml1-transitional.dtd">
%xhtml1-transitionalDTD;

さらら: あら。パラメータエンティティの宣言とその展開しかないわ。

たけち: うん。そうなんだけれど、このDTDを使うと、以下のようなXMLデータを検証することができるんだよ。

XMLデータ例: 【extendReport2.dtd】で検証可能
<?xml version="1.0" encoding="Shift_JIS" ?>
<!DOCTYPE report SYSTEM "extendReport2.dtd">
<report>
    <heading>万葉集総論</heading>
    <author>万葉一郎</author>
    <extendContents>
        <img src="nara1.jpg" alt="奈良全景" />
        <p>万葉の時代に触れるために、まず<strong>万葉集</strong>を開いてみよう。</p>
        <p>そこでは、<br />万葉の人達の息遣いが聞こえるようだ。</p>
    </extendContents>
</report>

さらら: うわぁ〜、XHTMLの要素がそのままextendContents要素の中で使えたのね。ANYって、将来拡張する可能性もある場合にとても便利なんだわ。

たけち: そう。だけど実際にはほとんど使われていない内容モデルだよね。

さらら: えっ、そうなの? でも、どうして?


■DTDのANYの問題点

たけち: まず、スキーマを構築する人の頭に、こういう拡張性を考える余裕がないことが少なくない、というのも理由の一つかもしれないね。ただ、DTDのANY自身にも以下のような問題点があるんだよ。

  1. ANYの部分にはDTDで定義されるすべての要素が出現可能であるため、意図しない要素まで出現を許してしまう。
  2. 参照する側のDTDでは、参照される側のDTDの中で定義されているのと同じ名前の要素の要素型宣言が出現してはならない。また参照されるDTDが複数あるとき、それらの中に同じ名前の要素の要素型宣言が存在してはならない。

さらら: あっ、そっか〜。

たけち: 2.については、既に以前、名前空間について説明したときに問題にしたことだから今更言うまでもないよね。

さらら: 2.の問題があるから、名前空間が必要だということよね。1.は具体的にどういうことなの?

たけち: 例えば次の例を見てみよう。

XMLデータ例: 意図しない要素まで出現を許してしまう
<?xml version="1.0" encoding="Shfit_JIS" ?>
<!DOCTYPE report SYSTEM "report.dtd">
<report>
    <heading>これっておかしい?</heading>
    <author>変人一郎</author>
    <extendContents>
        <author>変人二郎</author>でーす。
        <heading>おかしいよね</heading>あれ?
        <heading>やっぱりおかしいか</heading>
    </extendContents>

</report>

たけち: 【report.dtd】の定義からすると、このXMLデータは間違っていないんだ。だけど、こういうXMLデータを作るために、DTDでANYを使ったんじゃないよね。

さらら: そうね。こんなXMLデータを許すなんて考えていなかったわ。

たけち: ところが、DTDのANYを使うと、今度はもう見境なくDTDで定義されたすべての要素が、テキストと混在できる形で出現可能になってしまうんだ。一般に、任意の要素の出現を許可したいのは、既に宣言された要素ではなくて、別に宣言された要素であるケースの方が圧倒的に多いだろうね。でも、そういう仕分けはDTDのANYではできないんだ。

さらら: う〜ん、そういうのってちょっと困った点ね。

たけち: というところで、話をXML Schemaに戻してみることにするね。

さらら: あっ、そうだったわね。xsd:anyのお話をしてくれるんだったわね。(^ ^;

たけち: ちょっと長くなったので、次回こそxsd:anyについてお話するね。

さらら: あっ、は〜い。

次回はxsd:any(2)です...... (^ ^;

さらら

XMLスキーマのコーナーは、TAKABEさま(XSLTの遊び部屋)の全面的なご協力をいただいて作成しています。