私は定期的にいくつかのXMLファイルを処理しており、DTDが提供できるよりも優れた検証を行いたいと考えています。そこで、スキーマについて読み始めて、役立つかどうかを確認しました。これまでのところ、1つのピースを除いて、必要なものとほぼ同じように機能するものを作成することができました。要素の属性を、同じ要素タイプの兄弟要素または祖先要素の別の属性の値に制限できるようにしたい。これは、XMLスキーマのキー/キー参照の制限でも可能ですか?
次のようなドキュメントがあります。
<nodeContainer>
    <node name="Table">
    </node>
    <node name="MyHouse">
        <node name="RoomWithDoor">
        </node>
        <node name="DiningRoom" extends="RoomWithDoor">
            <node name="DiningTable" extends="Table">
            </node>
        </node>
    </node>
    <node name="MySummerHouse">
        <node name="DiningRoom">
            <node name="DiningTable" extends="Table">
            </node>
        </node>
    </node>
</nodeContainer>
このドキュメントでは、ノードは次のような他のノードを「拡張」できます。
- 兄弟
- 親の兄弟
ただし、ノードは「拡張」しないでください。
- 両親
- 親の兄弟の子ノード
これは、MyHouseがテーブルを「拡張」できることを意味します。これは意味がありませんが、私はそれで問題ありません。
また、両方のハウスノードがDiningRoomという名前の独自のノードを持つことができる必要があることも重要です。
そして、私の現在のスキーマはこれに似ています:
<xs:complexType name="node">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="node"/> <!-- node can have other nodes inside it -->
        <xs:element ref="leaf"/>
    </xs:choice>
    <xs:attribute name="name"       type="xs:anySimpleType" use="required"/>
    <xs:attribute name="extends"    type="xs:anySimpleType"/>
</xs:complexType>
<!-- document root -->
<xs:element name="root">
    <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
            <xs:element name="nodeContainer">
                <xs:complexType>
                    <xs:choice minOccurs="0" maxOccurs="unbounded">
                        <xs:element ref="node"/>    
                    </xs:choice>
                </xs:complexType>
            </xs:element>
            <xs:element ref="otherType"/>
        </xs:choice>
    </xs:complexType>
    <!-- create constrictions -->
    <xs:unique name="UniqueNodes">
        <xs:selector xpath="nodeContainer/node"/>
        <xs:field xpath="@name"/>
    </xs:unique>
    <xs:keyref refer="UniqueNodes" name="ValidNodeExtends">
        <xs:selector xpath=".//node"></xs:selector>
        <xs:field xpath="@extends"></xs:field>
    </xs:keyref>
</xs:element>
このスキーマは、私が探しているものの一部を実行します。キーをnodeContainerのノードの最初のレベルの名前に設定し、それらのキーを使用して、 nodeContainer以下の任意のレベルの任意のノードを「拡張」できます。そして、それは私がより低いレベルで兄弟を「拡張」したくない限り機能します。上記のサンプルドキュメントは、次の行のために検証されません。
<node name="DiningRoom" extends="RoomWithDoor">
私が作成したスキーマでは、 RoomWithDoorは、 nodeContainerのノードの最初のレベルの一部ではないため、「extends」に割り当てる有効なキーではありません。しかし、それらを有効なキーにするためにキー/キー参照を書く方法はありますか?キー/keyref定義の配置に違いはありますか?私のxpathはあまりにも具体的ですか(どうしてそれらはあまり具体的ではないのですか)?