次は複合型を制限した複合型です。
同じく下記の XML インスタンスを使用しましょう。
<root>
<sub1>
<child1>aaa</child1>
<child2>bbb</child2>
<child3>ccc</child3>
</sub1>
<sub2>
<child1>aaa</child1>
<child2>bbb</child2>
<child3>ccc</child3>
<child4>ddd</child4>
</sub2>
</root>
前回は、sub2 を sub1 の拡張とみなしました。
しかし sub1 は sub2 を制限したものともみなせます。
その場合、XML Schema は下記のようになります。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="sub1" type="sub1Type"/>
<xsd:element name="sub2" type="sub2Type"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="sub1Type">
<xsd:complexContent>
<xsd:restriction base="sub2Type">
<xsd:sequence>
<xsd:element name="child1" type="xsd:string"/>
<xsd:element name="child2" type="xsd:string"/>
<xsd:element name="child3" type="xsd:string"/>
</xsd:sequence>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="sub2Type">
<xsd:sequence>
<xsd:element name="child1" type="xsd:string"/>
<xsd:element name="child2" type="xsd:string"/>
<xsd:element name="child3" type="xsd:string"/>
<xsd:element name="child4" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
xsd:sequence を使用する場合、minOccurs="0" をはずすことはできません。
要はもともとの定義の時点で「消えても大丈夫」なように定義しなきゃならないのです。
前回の拡張と違って、XML インスタンス文書が下記のように変更になったとしても変更する場所は 2 箇所です。
<root>
<sub1>
<child2>bbb</child2>
<child3>ccc</child3>
</sub1>
<sub2>
<child2>bbb</child2>
<child3>ccc</child3>
<child4>ddd</child4>
</sub2>
</root>
はじめから minOccurs="0" にしなきゃならないなら
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="sub1" type="subType"/>
<xsd:element name="sub2" type="subType"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="subType">
<xsd:sequence>
<xsd:element name="child1" type="xsd:string"/>
<xsd:element name="child2" type="xsd:string"/>
<xsd:element name="child3" type="xsd:string"/>
<xsd:element name="child4" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
これで十分なんですが・・・・
正直言って、私はこの拡張型を制限した拡張型に利点がほとんど見出せません。
xsd:choice や xsd:all を使用している場合でも、別に定義するのと手間はほとんど同じだし。
せいぜい、パース時に元の型と制限後の型の同期を保障してくれるぐらいでしょうか?
つまり、前述の変更が XML インスタンス文書にあったとして
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="sub1" type="sub1Type"/>
<xsd:element name="sub2" type="sub2Type"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="sub1Type">
<xsd:complexContent>
<xsd:restriction base="sub2Type">
<xsd:sequence>
<xsd:element name="child2" type="xsd:string"/>
<xsd:element name="child3" type="xsd:string"/>
</xsd:sequence>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="sub2Type">
<xsd:sequence>
<xsd:element name="child1" type="xsd:string"/>
<xsd:element name="child2" type="xsd:string"/>
<xsd:element name="child3" type="xsd:string"/>
<xsd:element name="child4" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
としても
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="sub1" type="sub1Type"/>
<xsd:element name="sub2" type="sub2Type"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="sub1Type">
<xsd:complexContent>
<xsd:restriction base="sub2Type">
<xsd:sequence>
<xsd:element name="child1" type="xsd:string"/>
<xsd:element name="child2" type="xsd:string"/>
<xsd:element name="child3" type="xsd:string"/>
</xsd:sequence>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="sub2Type">
<xsd:sequence>
<xsd:element name="child2" type="xsd:string"/>
<xsd:element name="child3" type="xsd:string"/>
<xsd:element name="child4" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
としても XML Schema としてエラーになるってことです。
保守時に多少は助かるのかな?