问题
For a card-game that I am supposed to design, I have the task of implementing an attribute that can only have values that two other attributes can have. I already asked a question close to this one, where I was able to restrict that attribute to have the same value as another attribute. However, when it has not the same value, the compiler is giving an error message.
Background: I have the element "card" which is divided into the element "type" (which also defines a "color" as an attribute) and "annotation" which can have several attributes, for example "function" and "until" (see the example):
<card>
<type color="black">One</type>
<annotation function="drawcards">1</annotation>
</card>
The attribute in question is the attribute "until" that should only be able to have values from the attributes "color" or "function", which are determined by enumerations and can only have certain values:
<xs:simpleType name="color">
<xs:restriction base="xs:string">
<xs:enumeration value="black"/>
<xs:enumeration value="red"/>
<xs:enumeration value="blue"/>
<xs:enumeration value="green"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="function">
<xs:restriction base="xs:string">
<xs:enumeration value="drawcards"/>
<xs:enumeration value="cancel_turn"/>
<xs:enumeration value="reverse"/>
<xs:enumeration value="throwcards"/>
</xs:restriction>
</xs:simpleType>
So far I was able to determine the attribute "until" by using <xs:assert test="if (@until) then (@until = type/@color) or (@until = annotation/@function) else not (@until)"/>
However - this doesn't allow me to give another value to the attribute "until" than the value of "color" or "function". So the following example is not valid even though it should:
<card>
<type color="black">Five</type>
<annotation function="reverse" until="red">1</annotation>
</card>
How do I need to write in the assert in order to make any value that "color" or "function" could have also a valid value for "until"?
回答1:
Well, one way to do this would be to list the allowed values:
<xs:simpleType name="until">
<xs:restriction base="xs:string">
<xs:enumeration value="black"/>
<xs:enumeration value="red"/>
<xs:enumeration value="blue"/>
<xs:enumeration value="green"/>
<xs:enumeration value="drawcards"/>
<xs:enumeration value="cancel_turn"/>
<xs:enumeration value="reverse"/>
<xs:enumeration value="throwcards"/>
</xs:restriction>
</xs:simpleType>
But of course, you want to avoid duplicating the lists, so what you really want to do is to define a type that allows anything that the two other types allow. You can do this with a union:
<xs:simpleType name="until">
<xs:union memberTypes="color function"/>
</xs:simpleType>
This doesn't need XSD 1.1 and it doesn't need an assertion, because the allowed values for until
(if I've understood you correctly) don't depend on what's seen elsewhere in the instance, they only depend on what's in the schema.
来源:https://stackoverflow.com/questions/65637303/xsd-1-1-attribute-is-supposed-to-only-have-values-of-another-attribute