Search code examples
xmlxsdkeyrefminoccurs

XML Schema: keyref with optional field


I wonder if it's possible to use keyref element with optional fields.

e.g. Given the following schema:

<element name="myElement" type="myType">
    <complexType>
        <sequence>
            <element name="subElem">
                <complexType>
                    <attribute name="name" type="string"/>
                    <attribute name="type" type="string"/>
                </complexType>
            </element>
            <element name="subElem2">
                <complexType>
                    <sequence>
                        <element name="subSubElem" minOccurs="0">
                            <complexType>
                                <attribute name="type" type="string"/>
                            </complexType>
                        </element>
                    </sequence>
                    <attribute name="name" type="string" use="required"/>
                </complexType>
            </element>
        </sequence>
    </complexType>
    <key name="uniqueSubElem">
        <selector xpath="subElem"/>
        <field xpath="@name"/>
        <field xpath="@type"/>
    </key>
    <keyref name="uniqueSubElemRef" refer="uniqueSubElem">
        <selector xpath="subElem2"/>
        <field xpath="@name"/>
        <field xpath="subSubElem/@type"/>
    </keyref>
</element>

In this example if I don't specify a subSubElem in the XML the validator will complain:

Not enough values specified for <keyref name="uniqueSubElem"> identity constraint specified for element "myElement".

I need both the minOccurs="0" and the keyref constraint, and if the field is not present simply don't want any check to be performed (as for NULL FOREIGN KEYs).

EDIT: Ignore namespaces for this example, I used default namespace for everything...


Solution

  • I hope I understood your problem correctly. In your schema, you need to enclose <sequence> in <complexType>, and you need to close the field pointing to "subSubElem/@type":

    <xs:element name="myElement">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="subElem">
                    <xs:complexType>
                        <xs:attribute name="name" type="xs:string"/>
                        <xs:attribute name="type" type="xs:string"/>
                    </xs:complexType>
                </xs:element>
                <xs:element name="subElem2">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element minOccurs="0" name="subSubElem">
                                <xs:complexType>
                                    <xs:attribute name="type" type="xs:string"/>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                        <xs:attribute name="name" type="xs:string" use="required"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
        <xs:key name="uniqueSubElem">
            <xs:selector xpath="subElem"/>
            <xs:field xpath="@name"/>
            <xs:field xpath="@type"/>
        </xs:key>
        <xs:keyref name="uniqueSubElemRef" refer="uniqueSubElem">
            <xs:selector xpath="subElem2"/>
            <xs:field xpath="@name"/>
            <xs:field xpath="subSubElem/@type"/>
        </xs:keyref>
    </xs:element>
    

    This XML should validate without specifying a subSubElem:

    <myElement>
        <subElem name="foo" type="bar"/>
        <subElem2 name="foo2"/>
    </myElement>