ものがたり(旧)

atsushieno.hatenablog.com に続く

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に正しく拡張されるようになる。