Search code examples
xmlxsdannotationsattributesassert

XSD 1.1: Limit number of overall attributes for an element


I am working on a card-game which is supposed to display a number of states and change them depending on conditions. To realise this, I have an element <properties> that is given to each card as a mandatory element. Each property can have a series of attributes as seen in this example for xsd:

                        <xs:element name="properties" maxOccurs="1">
                            <xs:complexType>
                                <xs:attribute name="type" type="MyAttributeType"/>
                                <xs:attribute name="color" type="color"/>
                                <xs:attribute name="number" type="xs:integer"/>
                            </xs:complexType>
                        </xs:element>

These properties not only display the properties of each card but they also set the properties of the overall game-field. Now I have the task to make it possible that a card can change these properties of the game-field in dependence of its own properties. For this I am supposed to implement a type connected_condition which is only triggered, when a certain condition is true. For example:

<connected_condition><properties color='red'/><properties color='green'/></connected_condition/>

This condition for example is supposed to change the color of the game-field to green instead of red, when a card with the property "red" is displayed.

However - since we are dealing with attributes here, a connected_condition like this could be valid but would violate the task I have to fullfill:

<connected_condition><properties color='red' type='heart'/><properties color='green'/></connected_condition/>

An overall number of maximum two attributes are supposed to be valid in context of a connected_condition no matter if there is one or two elements of properties inside. But also the same property should be able to change (for example red to green) and I didn't find a way to use 2 times the same attribute in one element of properties within a connected_condition. To solve this, I am looking for a way to limit the overall number of attributes that can be used within the context of the element connected_condition. Preferably an assert hat says something like: "count all attributes from all child-elements within connected_condition and be false if there is more than 2". Also this should go without limiting the number of attributes being used in a single element properties that is given to each card itself. In the best possible outcome this would result in a card like this:

XSD:

                    <xs:element name="card">
                        <xs:complexType>
                            <xs:sequence>
                                <xs:element name='name' type='xs:string'/>
                                <xs:element name="properties" type='properties'/>          <!--should have all 3 of its attributes-->
                                <xs:element name='connected_condition' minOccurs='0' maxOccurs='1'>
                                    <xs:complexType>
                                        <xs:sequence>
                                            <xs:element name="properties" type='properties' maxOccurs='2'/>   <!--attributes limited to 2-->
                                        </xs:sequence>
                                    </xs:complexType>
                                </xs:element>
                            </xs:sequence>
                        </xs:complexType>
                    </xs:element>
                    <xs:simpleType name='properties'>
                        <xs:restriction base="xs:string">
                            <xs:attribute name="type" type="MyAttributeType"/>
                            <xs:attribute name="color" type="color"/>
                            <xs:attribute name="number" type="xs:integer"/>
                        </xs:restriction>
                    </xs:simpleType>

XML:

                        <card>
                            <name>Card 1</name>
                            <properties type='heart' color='red' number='7'/>
                            <connected_condition><properties color='red'/><properties color='green'/></connected_condition>
                            <text>Here goes the text</text>
                        </card>

Is there a way to limit the overall number of attributes when their element is used as a child-element using an assert?


Solution

  • I am not sure whether it is not better to restrict the type but an assertion in the form of

       <xs:element name="card">
            <xs:complexType>
                <xs:sequence>
                    <xs:element name='name' type='xs:string'/>
                    <xs:element name="properties" type='properties'/>          <!--should have all 3 of its attributes-->
                    <xs:element name='connected_condition' minOccurs='0' maxOccurs='1'>
                        <xs:complexType>
                            <xs:sequence>
                                <xs:element name="properties" type='properties' maxOccurs='2'/>   <!--attributes limited to 2-->
                            </xs:sequence>
                        </xs:complexType>
                    </xs:element>
                </xs:sequence>
                <xs:assert test="every $prop in connected_condition/properties satisfies count($prop/@*) le 2"/>
            </xs:complexType>
        </xs:element>
    

    might express your restriction on the number of attributes on each properties element inside of connected_condition.

    Your comment suggests you rather want <xs:assert test="count(connected_condition//@*) le 2"/>.