Вы приближаетесь.
В XSD 1.1 утверждения могут смотреть в поддерево только вниз, а не вверх или вверх, поэтому, если вы хотите использовать утверждения здесь, вам нужно поместить их не в тип для «состояния», а в тип для «адрес»:
<xs:element name="address">
<xs:complexType>
<xs:sequence>
<xs:element ref="street"/>
<xs:element ref="city"/>
<xs:element ref="state" minOccurs="0"/>
<xs:element ref="country"/>
</xs:sequence>
<xs:assert test="(country = 'UK' and not(state))
or
(country = 'US' and state = ('MA', 'AR', 'NY'))
or
(country = 'IN' and state = ('AP', 'TN', 'MP'))
"/>
</xs:complexType>
</xs:element>
Другой подход (также в XSD 1.1) заключается в использовании условного присвоения типа. Это позволяет назначать элементу разные типы на основе выражений XPath, которые могут ссылаться на его элементы (но не на его дочерние элементы). Если мы переместим страну и штат в атрибуты (а затем, для согласованности, также переместим улицу и город в атрибуты), мы могли бы использовать условное присвоение типа таким образом. Во-первых, определим различные простые типы, которые нам нужны для состояния:
<xs:simpleType name="US-states">
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="MA" />
<xs:enumeration value="AR" />
<xs:enumeration value="NY" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="IN-states">
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="AP" />
<xs:enumeration value="TN" />
<xs:enumeration value="MP" />
</xs:restriction>
</xs:simpleType>
Затем определите три разных сложных типа для трех разных типов адресов, которые нам нужны. Для иллюстрации я предполагаю, что адреса в Великобритании не имеют атрибута «штат».
<xs:complexType name="US-address">
<xs:attribute name="street" type="xs:string" use="required"/>
<xs:attribute name="city" type="xs:string" use="required"/>
<xs:attribute name="state" type="US-states"/>
<xs:attribute name="country" type="xs:NMTOKEN" use="required"/>
</xs:complexType>
<xs:complexType name="UK-address">
<xs:attribute name="street" type="xs:string" use="required"/>
<xs:attribute name="city" type="xs:string" use="required"/>
<xs:attribute name="country" type="xs:NMTOKEN" use="required"/>
</xs:complexType>
<xs:complexType name="IN-address">
<xs:attribute name="street" type="xs:string" use="required"/>
<xs:attribute name="city" type="xs:string" use="required"/>
<xs:attribute name="state" type="IN-states"/>
<xs:attribute name="country" type="xs:NMTOKEN" use="required"/>
</xs:complexType>
Теперь мы привязываем элемент address
к правильному из них на основе значения «страны»:
<xs:element name="address">
<xs:alternative test="@country='US'" type="US-address"/>
<xs:alternative test="@country='IN'" type="IN-address"/>
<xs:alternative test="@country='UK'" type="UK-address"/>
<xs:alternative type="xs:error"/>
</xs:element>
Альтернативы проверяются по порядку, и первая из них, проверка которой дает положительный результат, присваивает тип. Последняя альтернатива (без тестового атрибута) предоставляет значение по умолчанию, которое в данном случае является типом ошибки (никакие элементы или атрибуты не соответствуют типу ошибки).
person
C. M. Sperberg-McQueen
schedule
12.12.2012