XSD 1.1: Ограничение количества общих атрибутов для элемента

#xml #xsd #annotations #attributes #assert

Вопрос:

Я работаю над карточной игрой, которая должна отображать несколько состояний и изменять их в зависимости от условий. Чтобы понять это, у меня есть элемент <properties> , который дается каждой карточке в качестве обязательного элемента. Каждое свойство может иметь ряд атрибутов, как показано в этом примере для 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>
 

Они properties не только отображают свойства каждой карты, но и задают свойства всего игрового поля.
Теперь у меня есть задача сделать так, чтобы карта могла изменять эти свойства игрового поля в зависимости от своих собственных свойств. Для этого я должен реализовать тип connected_condition , который запускается только при выполнении определенного условия. Например:

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

Это условие, например, должно изменить цвет игрового поля на зеленый вместо красного, когда отображается карта со свойством «красный».

Однако — поскольку мы здесь имеем дело с атрибутами, connected_condition подобное может быть допустимым, но нарушит задачу, которую я должен выполнить:

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

Общее количество максимум двух атрибутов должно быть допустимым в контексте connected_condition , независимо от того, есть ли один или два элемента properties внутри. Но также одно и то же свойство должно быть в состоянии измениться (например, красный на зеленый), и я не нашел способа использовать 2 раза один и тот же атрибут в одном элементе свойств в a connected_condition . Чтобы решить эту проблему, я ищу способ ограничить общее количество атрибутов, которые могут использоваться в контексте элемента connected_condition . Предпочтительно шляпа утверждения говорит что-то вроде: «подсчитайте все атрибуты из всех дочерних элементов в connected_condition и будьте ложны, если их больше 2».
Также это должно происходить без ограничения количества атрибутов, используемых в одном элементе properties , который присваивается каждой карте. В лучшем случае это приведет к такой карте, как эта:

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>
 

Есть ли способ ограничить общее количество атрибутов, когда их элемент используется в качестве дочернего элемента с помощью утверждения?

Ответ №1:

Я не уверен, не лучше ли ограничить тип, но утверждение в форме

    <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>
 

это может выражать ваше ограничение на количество атрибутов каждого properties элемента внутри connected_condition .

Ваш комментарий наводит на мысль, что вы скорее хотите <xs:assert test="count(connected_condition//@*) le 2"/> .

Комментарии:

1. К сожалению, я не могу подтвердить. Кажется, это ничего не меняет. При применении его к коду и последующем добавлении более 1 атрибута на свойство он остается действительным.

2. @DanielJanz, ваше описание было неясным, например, в образце указано «атрибуты ограничены 2», а опубликованный таким образом код count($prop/@*) le 2 допускает до двух атрибутов ( le 2 «меньше или равно 2»). Измените номер на 1 , если это то, что вы хотели. Я даже не уверен, хотите ли вы проверить каждый properties элемент или все из них, опубликованный код предполагает, что вы хотите проверить количество атрибутов каждого properties дочернего элемента connected_connection элемента.

3. Ах нет, извините за неудобства. Речь идет о количестве всех атрибутов, суммированных по всему properties элементу внутри connected_condition . Поэтому независимо от того, есть ли только один properties элемент или два, общее количество атрибутов, используемых внутри connected_condition , не должно превышать двух.

4. Больше никаких идей о том, как справиться с этой задачей? Я все еще в растерянности.

5. Не помогает ли редактирование с <xs:assert test="count(connected_condition//@*) le 2"/> помощью?