名前付きモデルグループ

2002年10月13日(日)更新


■子要素の異なる複数の歌の例

たけち: 今まで3種類のモデルグループについて勉強してきたけれど、今日はそれらを便利に使うためのテクニックである「名前付きモデルグループ」について勉強してみるね。まずは、以下のXMLドキュメントとDTDを見てみてね。

さらら: あっ、いきなり・・・ (^ ^;

■万葉歌のXMLドキュメント例
<?xml version="1.0" encoding="Shift_JIS" ?>

<poems>

<miscellaneousPoem>
  <pno>1419</pno>
  <date>未詳</date>
  <poet>鏡王女</poet>
  <yomi>神なびの石瀬の社の呼子鳥いたくな鳴きそ我が恋まさる</yomi>
  <situation>橘諸兄宅宴席</situation>
  <season>春</season>
  <district>斑鳩</district>
  <emotion>恋愛</emotion>
</miscellaneousPoem>

<elegy>
  <pno>0146</pno>
  <date>大宝元年</date>
  <poet>柿本人麻呂</poet>
  <yomi>後見むと君が結べる磐代の小松がうれをまたも見むかも</yomi>
  <district>紀伊国</district>
  <source>柿本朝臣人麿歌集</source>
  <on>有間皇子</on>
</elegy>

<lovePoem>
  <pno>0085</pno>
  <date>難波の高津の宮に天の下知ろしめしし天皇の代</date>
  <poet>磐姫皇后</poet>
  <source>山上憶良臣類聚歌林</source>
  <emotion>恋愛</emotion>
  <sendTo>仁徳天皇</sendTo>
</lovePoem>

<metaphoricalPoem>
  <pno>0408</pno>
  <date>未詳</date>
  <poet>大伴家持</poet>
  <yomi>なでしこがその花にもが朝な朝な手に取り持ちて恋ひぬ日なけむ</yomi>
  <emotion>恋愛</emotion>
  <sendTo>坂上大嬢</sendTo>
</metaphoricalPoem>

</poems>

■万葉歌のDTD例
<!ELEMENT poems (miscellaneousPoem | elegy | lovePoem | metaphoricalPoem)*>

<!ELEMENT miscellaneousPoem (pno, date, poet, yomi, situation?, season?, district?, source?, emotion?)>

<!ELEMENT elegy (pno, date, poet, yomi, situation?, season?, district?, source?, emotion?, on)>

<!ELEMENT lovePoem (pno, date, poet, yomi, situation?, season?, district?, source?, emotion?, sendTo)>

<!ELEMENT metaphoricalPoem (pno, date, poet, yomi, situation?, season?, district?, source?, emotion?, sendTo)>

<!ELEMENT pno (#PCDATA)>
<!ELEMENT date (#PCDATA)>
<!ELEMENT poet (#PCDATA)>
<!ELEMENT yomi (#PCDATA)>
<!ELEMENT situation (#PCDATA)>
<!ELEMENT season (#PCDATA)>
<!ELEMENT district (#PCDATA)>
<!ELEMENT source (#PCDATA)>
<!ELEMENT emotion (#PCDATA)>
<!ELEMENT on (#PCDATA)>
<!ELEMENT sendTo (#PCDATA)>

さらら: うぅん、長〜〜い (^ ^;) .....でも、これって似たようなものをどこかで見たことがある気がするわ。

たけち: そうだね。以前「名前付き属性グループ」を勉強したときに、属性がたくさんある例を出したけれど、今度はそれを要素がたくさんある例に改造したんだね (^ ^;)

さらら: あっ、そうだったわね。。。。そうなってくると、何か、もう今回の話の筋は読めたような気が......(^ ^;)
でも、あのときと比べるとDTDはさほど面倒じゃないわね。

たけち: そうだね。あのときと比べると、要素の宣言が共有できているからね。ただ、だからといって全然無駄がないかというとそうでもないんだよ。このDTDの

さらら

<!ELEMENT poems (miscellaneousPoem | elegy | lovePoem | metaphoricalPoem)*>

<!ELEMENT miscellaneousPoem (pno, date, poet, yomi, situation?, season?, district?, source?, emotion?)>

<!ELEMENT elegy (pno, date, poet, yomi, situation?, season?, district?, source?, emotion?, on)>

<!ELEMENT lovePoem (pno, date, poet, yomi, situation?, season?, district?, source?, emotion?, sendTo)>

<!ELEMENT metaphoricalPoem (pno, date, poet, yomi, situation?, season?, district?, source?, emotion?, sendTo)>

たけち: の部分では、結構同じ記載の繰り返しからできているよね。

さらら: あっ、なるほど、そうね。

たけち: この部分をパラメータエンティティを使ってまとめてみようね。さらら、できるかな?

さらら: え゛っ (^ ^;

たけち: うん。じゃあ、長いから抽出した部分だけを、書き直してみるね。

たけち

<!ENTITY % poem_common
       "pno, date, poet, yomi, situation?, season?, district?, source?, emotion?">


<!ELEMENT miscellaneousPoem (%poem_common;)>

<!ELEMENT elegy                   (%poem_common;, on)>

<!ELEMENT lovePoem             (%poem_common;, sendTo)>

<!ELEMENT metaphoricalPoem (%poem_common;, sendTo)>

さらら: そんなに目だって短くなった気はしないけれども、でもこうしてまとめるとすっきり綺麗だわ。

たけち: そうだね。こういうふうにパラメータエンティティは、共通の要素の並びをまとめることもできるんだ。さて、話をXML Schemaの方にもどそうね。最初のDTDに相当するXML Schemaを書けるかな。今までの応用だよ。

さらら: どきっ!! (^ ^;

さらら


■XML Schemaで共通の要素の並びを定義

たけち: ただ、XML SchemaとDTDの違いに注意してね。DTDでは属性にしかNMTOKEN型や列挙型が使えなかったね。つまり要素にはNMTOKEN型や列挙型が使えなかったから、上記のDTDではpnoやseasonを#PCDATAで宣言しているね。
それに対して、XML Schemaでは要素も属性も関係なく同じ単純型である列挙型が使えるから、上記の例では列挙型を使ったseasonにしてみようね。それからNMTOKEN型については、これはあくまでDTDとの互換性を保つためにXML Schemaに導入されたデータ型なので、属性にしか使うべきじゃないから、ここではpositiveInteger型にしてみるね。

さらら: あとデフォルト値の設定もあったわねぇ。

たけち: そうだねぇ...確かにそうなんだけれど、今回の例ではあまりうまくいかないから、これは無視していいよ。今回、要素を参照する側で設定するデフォルト値を変えたいけれど、本来デフォルト値の設定は要素宣言からしかできない。ということは、同じデフォルト値をもった要素を宣言するということになると、本来したいことから意味が外れるし、そうでなければ、ローカル要素というものを使うしかない。だけど、ローカル要素の意味や使い方についてはまだ説明していないからね。今回はデフォルト値の設定はやめておくね。

さらら: よく意味がわからないけれど、デフォルト値については無視して、そこはDTDのとおりでいいのね。。。。poems要素の子供には、miscellaneousPoem、elegy、lovePoem、metaphoricalPoemのいずれかが出てくればいいからchoiceかしらね。それから。。。。。う〜ん、ややこしいけれど、こうかしら。。。。

さらら

■XML Schema by さらら
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="poems" type="PoemsType" />

<xsd:complexType name="PoemsType">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="miscellaneousPoem" />
<xsd:element ref="elegy" />
<xsd:element ref="lovePoem" />
<xsd:element ref="metaphoricalPoem" />
</xsd:choice>
</xsd:complexType>

<xsd:element name="miscellaneousPoem" type="MiscellaneousPoemType" />
<xsd:element name="elegy" type="ElegyType" />
<xsd:element name="lovePoem" type="LovePoemType" />
<xsd:element name="metaphoricalPoem" type="MetaphoricalPoemType" />

<xsd:complexType name="MiscellaneousPoemType">
<xsd:sequence>
<xsd:element ref="pno" />
<xsd:element ref="date" />
<xsd:element ref="poet" />
<xsd:element ref="yomi" />
<xsd:element ref="situation" minOccurs="0" />
<xsd:element ref="season" minOccurs="0" />
<xsd:element ref="district" minOccurs="0" />
<xsd:element ref="source" minOccurs="0" />
<xsd:element ref="emotion" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="ElegyType">
<xsd:sequence>
<xsd:element ref="pno" />
<xsd:element ref="date" />
<xsd:element ref="poet" />
<xsd:element ref="yomi" />
<xsd:element ref="situation" minOccurs="0" />
<xsd:element ref="season" minOccurs="0" />
<xsd:element ref="district" minOccurs="0" />
<xsd:element ref="source" minOccurs="0" />
<xsd:element ref="emotion" minOccurs="0" />
<xsd:element ref="on" />
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="LovePoemType">
<xsd:sequence>
<xsd:element ref="pno" />
<xsd:element ref="date" />
<xsd:element ref="poet" />
<xsd:element ref="yomi" />
<xsd:element ref="situation" minOccurs="0" />
<xsd:element ref="season" minOccurs="0" />
<xsd:element ref="district" minOccurs="0" />
<xsd:element ref="source" minOccurs="0" />
<xsd:element ref="emotion" minOccurs="0" />
<xsd:element ref="sendTo" />
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="MetaphoricalPoemType">
<xsd:sequence>
<xsd:element ref="pno" />
<xsd:element ref="date" />
<xsd:element ref="poet" />
<xsd:element ref="yomi" />
<xsd:element ref="situation" minOccurs="0" />
<xsd:element ref="season" minOccurs="0" />
<xsd:element ref="district" minOccurs="0" />
<xsd:element ref="source" minOccurs="0" />
<xsd:element ref="emotion" minOccurs="0" />
<xsd:element ref="sendTo" />
</xsd:sequence>
</xsd:complexType>

<xsd:element name="pno" type="xsd:positiveInteger" />
<xsd:element name="date" type="xsd:string" />
<xsd:element name="poet" type="xsd:string" />
<xsd:element name="yomi" type="xsd:string" />
<xsd:element name="situation" type="xsd:string" />
<xsd:element name="season" type="SeasonType" />
<xsd:element name="district" type="xsd:string" />
<xsd:element name="source" type="xsd:string" />
<xsd:element name="emotion" type="xsd:string" />
<xsd:element name="sendTo" type="xsd:string" />
<xsd:element name="on" type="xsd:string" />

<xsd:simpleType name="SeasonType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="春" />
<xsd:enumeration value="夏" />
<xsd:enumeration value="秋" />
<xsd:enumeration value="冬" />
</xsd:restriction>
</xsd:simpleType>

</xsd:schema>


■名前付きモデルグループ

さらら: きゃ〜、自分で書いてみたけど、やっぱり長〜い (^ ^; どっ、どうしたらいいのかしら。

たけち: 長いけど、そうだね。こんな感じだね。これを「名前付きモデルグループ」を使って次のように書き換えることができるんだよ。

さらら

■モデルグループを使って書いてみると・・・
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="poems" type="PoemsType" />

<xsd:complexType name="PoemsType">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="miscellaneousPoem" />
<xsd:element ref="elegy" />
<xsd:element ref="lovePoem" />
<xsd:element ref="metaphoricalPoem" />
</xsd:choice>
</xsd:complexType>

<xsd:element name="miscellaneousPoem" type="MiscellaneousPoemType" />
<xsd:element name="elegy" type="ElegyType" />
<xsd:element name="lovePoem" type="LovePoemType" />
<xsd:element name="metaphoricalPoem" type="MetaphoricalPoemType" />

<xsd:group name="poem_common">
<xsd:sequence>
<xsd:element ref="pno" />
<xsd:element ref="date" />
<xsd:element ref="poet" />
<xsd:element ref="yomi" />
<xsd:element ref="situation" minOccurs="0" />
<xsd:element ref="season" minOccurs="0" />
<xsd:element ref="district" minOccurs="0" />
<xsd:element ref="source" minOccurs="0" />
<xsd:element ref="emotion" minOccurs="0" />
</xsd:sequence>
</xsd:group>


<xsd:complexType name="MiscellaneousPoemType">
<xsd:group ref="poem_common" />
</xsd:complexType>

<xsd:complexType name="ElegyType">
<xsd:sequence>
<xsd:group ref="poem_common" />
<xsd:element ref="on" />
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="LovePoemType">
<xsd:sequence>
<xsd:group ref="poem_common" />
<xsd:element ref="sendTo" />
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="MetaphoricalPoemType">
<xsd:sequence>
<xsd:group ref="poem_common" />
<xsd:element ref="sendTo" />
</xsd:sequence>
</xsd:complexType>

<xsd:element name="pno" type="xsd:positiveInteger" />
<xsd:element name="date" type="xsd:string" />
<xsd:element name="poet" type="xsd:string" />
<xsd:element name="yomi" type="xsd:string" />
<xsd:element name="situation" type="xsd:string" />
<xsd:element name="season" type="SeasonType" />
<xsd:element name="district" type="xsd:string" />
<xsd:element name="source" type="xsd:string" />
<xsd:element name="emotion" type="xsd:string" />
<xsd:element name="sendTo" type="xsd:string" />
<xsd:element name="on" type="xsd:string" />

<xsd:simpleType name="SeasonType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="春" />
<xsd:enumeration value="夏" />
<xsd:enumeration value="秋" />
<xsd:enumeration value="冬" />
</xsd:restriction>
</xsd:simpleType>

</xsd:schema>

さらら: DTDと同じ感じのまとまり方なのね。

たけち: そうだね。ここで見てもらいたいのは、

    <xsd:group name="poem_common">
    <xsd:sequence>
    <xsd:element ref="pno" />
    <xsd:element ref="date" />
    <xsd:element ref="poet" />
    <xsd:element ref="yomi" />
    <xsd:element ref="situation" minOccurs="0" />
    <xsd:element ref="season" minOccurs="0" />
    <xsd:element ref="district" minOccurs="0" />
    <xsd:element ref="source" minOccurs="0" />
    <xsd:element ref="emotion" minOccurs="0" />
    </xsd:sequence>
    </xsd:group>


の部分なんだ。このモデルグループに名前をつけて定義しているんだね。

さらら: name="poem_common"というのがモデルグループの名前なのね。

たけち: そうそう。このように

    <xsd:group name="モデルグループの名前">
    sequenceかchoiceかallのどれかのモデルグループ
    </xsd:group>


 という形で名前付きモデルグループは定義されるんだ。そしてその定義した名前付きモデルグループを参照しているのが、

    <xsd:group ref="poem_common" />

 の部分なんだ。

さらら: ふ〜ん。そうなんだ。

たけち: ちなみに

    <xsd:sequence>
    <xsd:group ref="poem_common" />
    <xsd:element ref="sendTo" />
    </xsd:sequence>
>

 と書くとそれは、

    <xsd:sequence>
    <xsd:sequence>
    <xsd:element ref="pno" />
    <xsd:element ref="date" />
    <xsd:element ref="poet" />
    <xsd:element ref="yomi" />
    <xsd:element ref="situation" minOccurs="0" />
    <xsd:element ref="season" minOccurs="0" />
    <xsd:element ref="district" minOccurs="0" />
    <xsd:element ref="source" minOccurs="0" />
    <xsd:element ref="emotion" minOccurs="0" />
    </xsd:sequence>

    <xsd:element ref="sendTo" />
    </xsd:sequence>


  という意味になるんだ。

さらら: sequenceが重なっちゃってるわ。

たけち: そうそう。必ず1回しか出現しないsequenceばかりを、何回どれだけネストしたり並べたりしようが、それは一つのsequenceで挟まれたものと同じ意味だよね。この例も、

    <xsd:sequence>
    <xsd:element ref="pno" />
    <xsd:element ref="date" />
    <xsd:element ref="poet" />
    <xsd:element ref="yomi" />
    <xsd:element ref="situation" minOccurs="0" />
    <xsd:element ref="season" minOccurs="0" />
    <xsd:element ref="district" minOccurs="0" />
    <xsd:element ref="source" minOccurs="0" />
    <xsd:element ref="emotion" minOccurs="0" />

    <xsd:element ref="sendTo" />
    </xsd:sequence>


 と実は同じ意味になるんだ。

さらら: なるほど、そうなるのね。


■名前付きモデルグループでの注意事項

たけち: あと「名前付きモデルグループ」で気をつけないといけないのは、出現頻度の設定なんだよ。上の例にあるように、「名前付きモデルグループ」の内部の方でパーティクルのminOccursやmaxOccursの出現頻度の設定をするのはいいんだけどね。例えば、

    <xsd:complexType name="PoemsType">
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
    <xsd:element ref="miscellaneousPoem" />
    <xsd:element ref="elegy" />
    <xsd:element ref="lovePoem" />
    <xsd:element ref="metaphoricalPoem" />
    </xsd:choice>
    </xsd:complexType>

 の部分を(簡潔に書くメリットはないけれど)「名前付きモデルグループ」で書き直してみようね。これは

    <xsd:complexType name="PoemsType">
    <xsd:group ref="poem" minOccurs="0" maxOccurs="unbounded" />
    </xsd:complexType>

    <xsd:group name="poem">
    <xsd:choice>
    <xsd:element ref="miscellaneousPoem" />
    <xsd:element ref="elegy" />
    <xsd:element ref="lovePoem" />
    <xsd:element ref="metaphoricalPoem" />
    </xsd:choice>
    </xsd:group>

 という書き方になるんだけれど、ここで見てもらいたいのは、minOccursやmaxOccursの出現頻度の設定をしているのは、「名前付きモデルグループ」の参照をしている、

    <xsd:group ref="poem" minOccurs="0" maxOccurs="unbounded" />

 だということだよ。名前付きグループの定義のところや、最外層のモデルグループであるchoiceのところで出現頻度の設定をしてはいけないんだ。

たけち

さらら: えっ、そうなの。

たけち: そうなんだ。たとえば、

    ※出現頻度:書いてはいけない例-1
    <xsd:group name="poem" minOccurs="0" maxOccurs="unbounded">
    <xsd:choice>
    <xsd:element ref="miscellaneousPoem" />
    <xsd:element ref="elegy" />
    <xsd:element ref="lovePoem" />
    <xsd:element ref="metaphoricalPoem" />
    </xsd:choice>
    </xsd:group>

 と書いてはいけないし、

    ※出現頻度:書いてはいけない例-2
    <xsd:group name="poem">
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
    <xsd:element ref="miscellaneousPoem" />
    <xsd:element ref="elegy" />
    <xsd:element ref="lovePoem" />
    <xsd:element ref="metaphoricalPoem" />
    </xsd:choice>
    </xsd:group>

 と書いてもいけないんだよ。名前付きモデルグループ内部のパーティクルの出現頻度は設定してもいいけれど、名前付きモデルグループ自体の出現頻度は、定義する際に設定してはいけない。これを設定してよいのは、名前付きグループの定義ではなくて参照する側だということも気をつけておこうね。

さらら: ふ〜ん、なんとなくわかったわ。

さらら

たけち: さて、次回なんだけれど... 以前、「名前付き属性グループ」の説明をした後に、「これと同じ結果をまた別の観点から得ることができる、もっとスマートな方法もある」と言って、「属性を追加する方法」つまり「拡張(extension)」を紹介したよね。

さらら: あっ、そうだったわね。 (^ ^;

たけち: というわけで、「名前付きモデルグループ」の説明をした後も、同じ流れで次回は「モデルグループの追加」をする「拡張(extension)」の話をするよ (^ ^;

さらら: は〜い。

次は、要素(モデルグループ)の追加です。。。。。 (^ ^*


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