XSD Inference (3)内容種別
(ちなみにこの一連のシリーズは、終わったら英訳wされてmonologueに投げられる予定)
3回目はいよいよ要素型の内容モデルの推測に入る。実際には、内容モデルには2つの構成要素がある。内容種別と内容グループだ。内容種別には、「空」「テキストのみ」「要素のみ」「混在」(empty, textOnly, elementOnly, mixed)の4種類がある。内容グループには、sequence, choice, all, およびグループ参照が含まれる。今回は内容グループは扱わない(これは長くなる)。
まずは繰り返しから。MS仕様のXmlSchemaInferenceでは、document element以外は全てルートとなる要素型の要素のcomplexTypeのparticleとして定義される(つまり、中に含まれる)。ただし例外があって、ルート要素と名前空間が異なる場合には、その要素は、内容モデルとしては単なる参照(xs:element ref='foo:bar')となり、その定義の実体は、生成結果のXmlSchemaSetに含まれる当該名前空間のXmlSchema(無ければ生成される)のグローバル要素として定義される。XML Schemaの文法では、そうしないと定義できないためだ。*1。
空要素の扱い
emptyこと空要素は、ある要素が空要素であったときに定義される(当たり前か)。IsEmptyElementがtrueであるか、あるいは内容が何も出てこないうちにEndElementが出現した場合に適用される。
空要素を推測するのに難しいことは無い。MS XmlSchemaInferenceでは、何も型情報を持たせないことで対応している。monoでは現状xs:stringを推測しているのだけど、実際には何も型情報を付加しない方が良いのかもしれない。ただしその設計では、XML Schema Structures 3.3.2の定義により、型はur-typeとなるという欠陥がある。
テキストが出現したとき
テキストが出現すると、simple contentを受け入れられる型にする必要が生じる。emptyであれば、xs:string型に変換する(なぜxs:string固定なのかは後述する)。既にtextOnlyであれば、(後述のように)型の調整を行う必要があるが、内容種別の変更は生じない。complexTypeをもつ場合、それがcomplex contentを持つ場合*2、そのcomplexTypeあるいはcomplexContentにmixed="true"を設定する。そうでなければ、simpleTypeが推測されているので、内容種別の変更は生じない(型の調整は行う)。
テキストのprimitive typeの推測
テキストの推測には、テキストのprimitive typeの推測も含まれる。ただしprimitive typeの推測は、特定の状況では発生しない:
- 既にその要素型がcomplexTypeであるとき。この場合、テキストが出現すると、そのcomplexTypeはmixedになる。mixedの場合、断続的に出現しうるテキストノードに対して、XML Schemaでは型を付加することはできないからである。
- 要素定義が既存のもので、空要素として推測されていた場合。この場合、受け入れられるデータ型はxs:stringだけである。空文字列でxs:intなどを受け入れることは出来ないためだ。
- 要素定義がXML Schema datatypesで定義されていないsimpleTypeを持っていた場合。現状、MS.NETでは、restrictionやlistやunionによる制約を考慮したsimpleTypeの値の検証を行うAPIが存在しない*3。だから、現在のテキスト値を検証することは出来ない。*4
これ以外の場合には、primitive typeの推測も行われる。このとき、その要素型が既に特定のprimitive typeである場合には、まずその型で現在のテキスト値が許容されるかどうかを試す。もし許容されるのであれば、そのまま型情報を保持しておけばよい。一方、もし許容されなかった場合、既存の型との間で、最大公約数をとらなければならない。*5
あるテキスト値からどのような型が推測されるかについては、今後の回で説明する。
要素が出現した場合
要素が出現すると、その親となる要素の型はcomplexContentをもつcomplexTypeになる。このとき:
- 要素型がsimpleTypeであった場合は、complexTypeに置き換えられる。
- 要素型がcomplexTypeで、simpleContentを持っている場合は、それはcomplexContentに置き換えられ、simpleContentの子要素で定義された全ての属性定義がコピーされる。complexContentはmixed="true"となり、テキストについて推測されたデータ型は破棄される。
その後、パーティクルの推測が行われることになるのだが…これを説明すると長くなるので次回。
*1:XML Schemaでは、外部名前空間に属する要素について、別々の内容モデルを定義することはできない。あるいは、ある要素は、外部名前空間から参照されるものについては、複数定義することは不可能だ
*2:SOMで言えば、XmlSchemaComplexTypeがParticleをもっているか、あるいはContentModelがXmlSchemaComplexContentである場合
*3:Microsoftに「追加してよ」ってsuggestionを投げたが、彼らは拒否している
*4:実際にはbaseTypeをさらっていくことも出来なくはないが、monoではxs:stringにしている。MS.NETではそもそもsimpleTypeが出現することは前提とされていない。
*5:monoでは現状xs:stringにしてしまっているが、これはいずれ修正されて、たとえばxs:byteはxs:shortに正しく拡張されるようになる。