You are getting closer.
In XSD 1.1, statements can only look in a subtree, not up or down, so if you want to use statements here, you will need to put them not in a type for state, but in a type for 'address:
<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>
Another approach (also in XSD 1.1) is to use conditional type assignment. This allows you to assign an element to different types based on XPath expressions that can reference its elements (but not its children). If we move the country and state into attributes (and then, for consistency, move the street and city into attributes), we could use a conditional type assignment in this way. First define the various simple types we want for the state:
<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>
Then define three different complex types for the three different types of addresses that we want. I assume, for illustration, that UK addresses do not receive the 'state' attribute.
<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>
Now we bind the address element to the correct one of them based on the value "country":
<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>
Alternatives are checked in order, and the first, whose test evaluates to true, assigns a type. The latter alternative (without the test attribute) provides a default value, which in this case is the type of error (there are no elements or attributes regarding the type of error).